@selfage/web_page_handlerdeprecated

Serving single page applications on top of expressjs.

Usage no npm install needed!

<script type="module">
  import selfageWebPageHandler from 'https://cdn.skypack.dev/@selfage/web_page_handler';
</script>

README

@selfage/web_page_handler

Install

npm install @selfage/web_page_handler

Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See @selfage/tsconfig for full compiler options. Provides handlers to serve HTTP GET requests to load web pages/single page applications (SPAs) on top of Express.js, based on web_page_mapping_config.json. See Mapping config to understand and define such config. You can use @selfage/cli to help prepare all files that are required before starting the web server and registering handlers.

Example config

Suppose we define the following config at ./web_page_mapping_config.json which is assumed to be available for the rest of the document.

{
  "pathsToTs": [{
    "path": "/some_page",
    "ts": "./simple_page",
    "js": "./simple_page_bin"
  }],
  "notFoundTs": {
    "path": "/some_not_found",
    "ts": "./simple_not_found",
    "js": "./simple_not_found_bin"
  },
  "pathsToStaticDirectories": [{
    "path": "/some_static",
    "dir": "./simple_static"
  }],
  "sourceMapSupport": {
    "path": "/some_source_map_support",
    "js": "./browser-source-map-support"
  }
}

Preparation

By using @selfage/cli and running selfage buildWebPages ./, we are expecting ./web_page_mapping_config.json, ./simple_page.ts, ./simple_not_found.ts, and ./browser-source-map-support.js. Those TypeScript files are the SPAs you are building. The last JavaScript file should be downloaded from source-map-support's GitHub repo. Note that all file/directory paths are paths relative to the directory of web_page_mapping_config.json. Then you will get the following files.

./simple_page_bin.js and ./simple_not_found_bin.js are already compiled, browserified, and uglified. ./simple_page_bin.js.gz, ./simple_not_found_bin.js.gz and ./browser-source-map-support.js.gz are gzipped from their correspoding JavaScript files.

./simple_page_bin.html (example) and ./simple_not_found_bin.html contain <script> tags with their src= attributes pointing to the url paths configured. ./simple_page_bin.html.gz and ./simple_not_found_bin.html.gz are their gzipped version.

Looking closely at ./simple_page_bin.html, it barely contains anything. <script type="text/javascript" src="/some_page.js"></script> is the most important part and we want to serve ./simple_page_bin.js or ./simple_page_bin.js.gz for it. As for why it's src="/some_page.js" not src="/some_page", /some_page needs to serve ./simple_page_bin.html or ./simple_page_bin.html.gz.

And for <script type="text/javascript" src="/some_source_map_support.js"></script>, we want to serve ./browser-source-map-support.js or ./browser-source-map-support.js.gz. But it's not helpful if ./simple_page_bin.js doesn't contain inline source maps and inline source. To get inline source maps and inline source, run selfage buildWebPages ./ --debug.

You can also provide an extra environment file to buildWebPages command. See this answer which is also referenced by @selfage/cli#browserify for hwo to do create and use an environment file.

Handlers

Actually, we don't expose a handler class/function to be registered. However, it's worth noting that the handler implemented here is simply serving static files prepared above, by serving the gzipped version if the browser accepts it, and returning 304 by if the ETag header doesn't change (which is an out-of-the-box feature from Express.js). Those static files will not be cached in-memory by the handler. A reverse proxy can be considered.

Register

We are only exposing a register function to register all needed handlers based on the mapping config.

import express = require("express");
import { registerWebPageHandlers } from '@selfage/web_page_handler';

let app = express();
registerWebPageHandlers(app, __dirname);

Note that you need to provide an absolute path to the directory containing web_page_mapping_config.json. Supposing the above code is written in ./main.ts, then it's good to go. But if it's in ./ui/main.ts, then you'd need path.join(__dirname, '..').

The server can now serve the prepared HTML and JavaScript files at the configured url paths, serve 404 error when no url paths match with additional response body, i.e. ./simple_not_found_bin.html, and serve static files based on express.static() (with maxAge set to 1d).