Static HTTP/2 webserver for single page apps and progressive web apps.
npm i -g @http2/server
http2server <command> [options]
Display the current version number.
List global or command-specific options.
Start the server
The environment variable
PORT sets the network port for incoming HTTPS connections. This overrides
https.port in the configuration file.
The unencrypted HTTP port, used for redirects, is derived by setting the last three digits set to
080. E.g. HTTPS
8443 -> HTTP
443 -> HTTP
Base directory to serve static files from. Defaults to
./public, if it exists, or
./ otherwise. This sets the
host.root for any host that has left the option undefined the configuration file.
Configuration file with options. Defaults to
./http2server.config.js, if it exists, or the default configuration otherwise. See the Configuration section for details.
Open browser window after starting the server. Default:
Sets the severity threshhold for log output. Choices:
Shuts down the server by sending it the
Gracefully restart workers with a new configuration by sending the server the
Loads and validates a server configuration.
Identical to the same option of the
See JSON schemas and defaults in
src/configuration for details.
The manifest is a declares which files or URLs need to be pushed as dependencies for any request.
Example: Push all CSS and JS files when serving the homepage.
glob: '**/*.html' push: '**/*.css' '**/*.js'
Page load time is a largely function of latency (round trip time × delays) and aggregate volume (number × size of assets).
Latency is minimised by using HTTP/2 Server Push to deliver any necessary assets to the browser alongside the HTML. When the browser parses the HTML it does not need to make a round trip request to fetch styles, scripts, and other assets. They are already in its cache or actively being pushed by the server as quickly as network conditions allow.
Volume is reduced by using strong compression (HPACK, Brotli, etc), and by avoiding sending redundant data.
The HTTP/1 approach was to use file signatures (Etags) and timestamps to invalidate cached responses. This requires many expensive round trips where the browser checks with the server if any files have been modified.
Cache Digests to the rescue! Using a clever technique, called Golomb-Rice Coded Bloom Filters, a compressed list of cached responses is sent by the browser to the server. Now the server can avoid pushing assets that are fresh in the browser's cache.
With Server Push and Cache Digests the best practice is to have many small files that can be cached and updated atomically, instead of large, concatenated blobs.
Browsers do not yet support cache digests natively so Service Workers and the Cache API are used to implement them. A cookie-based fallback is available for browsers that lack Service Worker support.
While the HTTP/2 specification allows unencrypted connections, web browsers strictly enforce HTTPS.
If no certificate and key are provided, one pair will be auto-generated. The generated certificate is only valid for
localhost. It is stored in
~/.http2server. As a user convenience, the certificate is added as trusted to the operating system so browsers will accept the certificate. A password dialog may appear to confirm. This is currently only supported on macOS and Linux.
In production use Let's Encrypt or any other trusted, signed certificate.
Intermediate certificates are stapled to the OCSP response to speed up the TLS handshake.
By default files are served with the header
cache-control: public, must-revalidate.
File paths that match the patterns set by the
cacheControl.immutable option are considered to never, ever change their contents. They are served with the header
cache-control: public, max-age=31536000, immutable. This tells browsers never to revalidate these resources.
Special named immutable patterns can be used as shorthand for complex but handy patterns.
hex— Matches hexadecimal hash revved files. Example:
emoji— Matches emoji revved files. Example:
Made with ❤️ by Sebastiaan Deckers in 🇸🇬 Singapore.