Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
https://nodejs.org| Installer Source| Releases (json) (tab)
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
https://nodejs.org| Installer Source| Releases (json) (tab)
To update or switch versions, run webi node@<tag>
.
(you can use @lts
for long-term support, @beta
for pre-releases, or @x.y.z
for a specific version)
These are the files / directories that are created and/or modified with this install:
~/.config/envman/PATH.env
~/.local/opt/node/
~/.node/
~/.node_repl_history
~/.npm/
~/.npmrc
Node is great for simple, snappy HTTP(S) servers, and for stitching APIs together with minimal fuss or muss.
Installing node via webi will:
$HOME/.local/opt/node/
PATH
in $HOME/.config/envman/PATH.env
sudo npm
permission errors)node -e 'console.log("Hello, World!")'
> Hello, World!
Just by installing these alone, most code editors (vim, VS Code, etc) can automatically use them for JavaScript:
npm install --location=global fixjson@1 jshint@2 prettier@3
To run them manually on your code;
touch .prettierrc.json .prettierignore
prettier -w '**/*.{md,js,jsx,html}'
touch .jshintrc .jshintignore
jhint -c ./.jshintrc *.js */*.js
fixjson -i 2 -w ./package.json
To run with GitHub Actions on PRs see "Fmt & Lint Automatically" below.
server.js
:
var http = require('http');
var app = function (req, res) {
res.end('Hello, World!');
};
http.createServer(app).listen(8080, function () {
console.info('Listening on', this.address());
});
node server.js
This generates a hex-encoded 128-bit random key.
node -p 'crypto.randomBytes(16).toString("hex")'
This generates a url-safe base64 256-bit random key.
node -p 'crypto.randomBytes(32).toString("base64")
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")'
mkdir my-server
pushd my-server/
npm init
npm install --save express
app.js
:
'use strict';
var express = require('express');
var app = express();
app.use('/', function (req, res, next) {
res.end('Hello, World!');
});
module.exports = app;
server.js
:
'use strict';
var http = require('http');
var app = require('./app.js');
http.createServer(app).listen(8080, function () {
console.info('Listening on', this.address());
});
npm start
You can use caddy:
./Caddyfile
:
localhost {
# Reverse Proxy to your Node app's API
handle /api/* {
reverse_proxy localhost:3000
}
# Handle static files directly with Caddy
handle /* {
root * ./public/
file_server
}
}
caddy run --config ./Caddyfile
See the Caddy Cheat Sheet for more info, such as how to use
X-SendFile
to .
You can... but should you?
Typically you should use caddy
as a Reverse Proxy (see above).
On macOS all programs have permissions to use privileged ports by default.
On Linux there are several ways to add network capabilities for privileged ports:
Use setcap-netbind
webi setcap-netbind
setcap-netbind caddy
Use setcap
directly
my_caddy_path="$( command -v caddy )"
my_caddy_absolute="$( readlink -f "${my_caddy_path}" )"
sudo setcap cap_net_bind_service=+ep "${my_caddy_absolute}"
Add the --set-cap-net-bind
option to serviceman
(see
below)
Update the systemd
config directly:
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
Also called "Login Item", "Startup Item" or "User Unit", this is how you run a Node app as a Non-System (Unprivileged) Service on Mac, Windows, and Linux:
Install serviceman
webi serviceman
Use Serviceman to create a Launch Agent (macOS), Startup Item (Windows), or User Unit (Linux):
my_username="$( id -u -n )"
serviceman add --user --name my-node-project -- \
caddy run --config ./Caddyfile --envfile ~/.config/caddy/env
Manage the service
On macOS
# Manage (-w to disable/enable on login)
launchctl unload -w ~/Library/LaunchAgents/my-node-project.plist
launchctl load -w ~/Library/LaunchAgents/my-node-project.plist
# View Logs
tail -f ~/.local/share/my-node-project/var/log/my-node-project.log
On Windows
# Manage
serviceman stop caddy
serviceman start caddy
# View Logs
type ~/.local/share/my-node-project/var/log/my-node-project.log | more
On Linux
# Manage
systemctl --user disable my-node-project
systemctl --user stop my-node-project
systemctl --user enable my-node-project
systemctl --user start my-node-project
# View Logs
journalctl --user -xef -u my-node-project
pushd ./my-node-project/
my_username="$( id -u -n )"
sudo env PATH="$PATH" \
serviceman add --system --path "$PATH" --cap-net-bind \
--name my-node-project --username "${my_username}" -- \
npm run start
pushd ./my-node-project/
sudo env PATH="$PATH" \
serviceman add --system --path "$PATH" --cap-net-bind \
--name my-node-project --username "$(id -u -n)" -- \
npx -p nodemon@3 -- nodemon ./server.js
sudo journalctl -xef -u my-node-project
sudo systemctl restart my-node-project
Here are some useful scripts to have in your package.json
, and a sample file
to run them with GitHub Actions (Workflows):
npm run
fmt
lint
bump <major|minor|patch|prerelease>
prepublish # also runs after npm install
# bump
npm pkg set scripts.bump='npm version -m "chore(release): bump to v%s"'
# fmt
npm pkg set scripts.fmt='npm run fixjson && npm run prettier'
npm pkg set scripts.prettier="npx -p prettier@2 -- prettier --write '**/*.{md,js,jsx,json,css,html,vue}'"
npm pkg set scripts.fixjson="npx -p fixjson@1 -- fixjson -i 2 -w '*.json' '*/*.json'"
echo 'node_modules' >> .prettierignore
# lint
npm pkg set scripts.lint='npm run jshint'
npm pkg set scripts.jshint="npx -p jshint@2 -- jshint -c ./.jshintrc ./*.js ./*/*.json"
echo 'node_modules' >> .jshintignore
# prepublish
npm pkg set scripts.prepublish='npm run lint && npm run fmt'
To run these automatically for all PRs on GitHub:
.github/workflows/node.js.yml
:
name: Node.js CI
on:
push:
branches: ['main']
pull_request:
jobs:
build:
name: "Fmt, Lint, & Test"
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 20.x
- latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: "Webi: Install 'shfmt' and 'shellcheck', and update PATH"
run: |
#sh ./_scripts/install-ci-deps
echo "${HOME}/.local/bin" >> $GITHUB_PATH
- run: node --version
- run: npm run fmt
- run: npm clean-install
- run: npm run lint
- run: npm run test