Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kapouer/express-dom
Prepare, render web pages - express middleware
https://github.com/kapouer/express-dom
dom express-middleware prerender
Last synced: 10 days ago
JSON representation
Prepare, render web pages - express middleware
- Host: GitHub
- URL: https://github.com/kapouer/express-dom
- Owner: kapouer
- License: mit
- Created: 2014-10-28T09:13:50.000Z (about 10 years ago)
- Default Branch: master
- Last Pushed: 2024-11-13T23:30:35.000Z (about 2 months ago)
- Last Synced: 2024-12-23T16:07:08.341Z (18 days ago)
- Topics: dom, express-middleware, prerender
- Language: JavaScript
- Homepage:
- Size: 565 KB
- Stars: 14
- Watchers: 3
- Forks: 1
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGES.md
- License: LICENSE
Awesome Lists containing this project
README
# express-dom
Express middleware for (pre)rendering web pages with [playwright](https://playwright.dev/docs/api/).
Uses system-installed chromium or google-chrome.
## Synopsis
```js
const express = require('express');
const app = express();
const dom = require('express-dom');app.get('*.html', dom(), express.static('public/'));
```To do rendering outside express middleware:
```js
// obj can be a url string, or an IncomingMessage,
// or an object with { url, status?, headers?, body? } properties
// status defaults to 200, headers to { Content-Type: 'text/html' }const res = await dom()(obj);
const { statusCode, headers, body } = res;
```A page is requested by a browser for three purposes:
- offline: hidden offline web page changed by outside scripts. Only done on server.
- online: hidden online web page built by its own scripts. Typical prerendering,
can be done on the server, or delegated to the user browser.
- visible: fully rendered page, usually happens on the user browser, is typically needed for
pdf rendering (see express-dom-pdf).Configuration functions can setup a handler instance, valid for all requests on that handler.
Routers can change settings depending on the current request.
Plugins can change page settings before it is loaded, and can run scripts when the page is 'idle'.
A phase is skipped if it has no registered plugins.
The 'idle' event is emitted on the `page` instance after DOMContentLoaded, and after requests have settled and custom or default tracker has resolved.
The listeners of the 'idle' event can be asynchronous and are run serially.
## Options
dom holds some global settings:
- browser: the playwright channel to use, defaults to 'chrome'
- executable: the path to a browser executable (optional)
- debug: show browser, disables timeout. Also set by `PWDEBUG=1`.
- defaults: per-instance settings
- pools: pages pools. Vary on visible and scale.
- plugins: map of plugins functions
- online, offline: per-phase settings defaultsMiddleware settings:
- log: boolean, or level (info, log, warn, error)
- timeout: async resources timeout
- scale: changes window.devicePixelRatio
- cookies (used only with cookies plugin)Handler properties:
- online, offline, visible: custom phase settings, takes precedence
Phase settings:
- policies: object for configuring Content-Security-Policies
- enabled: boolean
- track: boolean, or custom track function (see below)
- styles: list of css strings
- scripts: list of [function, arg?] pairs
- headers: object of response headers to add to page route
- plugins: list (set) of namesDefault offline settings:
- enabled: false
- track: false
- plugins: console, hidden, html
- policies: default: "'none'"Default online settings:
- enabled: true
- track: true
- plugins: console, hidden, cookies, referer, redirect, html
- policies:
- default: "'none'"
- script: "'self' 'unsafe-inline'"
- connect: "'self'"Mind that policies of the requesting phase are obtained from settings of the responding phase: route handler cannot change policies of current phase.
## tracker
If phase setting `track` is true, the default tracker waits for async operations:
- loading of script/link nodes
- DOMContentLoaded listeners
- fetch, xhr calls
- timeouts (capped by page timeout)
- animation frame requests
- microtasksOtherwise, `track` can be a custom async function that is evaluated by the default tracker to determine when the page has settled.
When `track` is false, the idle event just wait for first batch of files to be loaded.
## Route settings
Route-dependent configuration can be done by passing to `dom()`:
- an object with `{ online, offline, visible }` settings
- a function accepting a `handler` instance as argument## Phase settings
Configuration depending on the route and the phase can be set using a router function accepting (phase, req, res) as argument.
```js
dom().route((phase, req, res) => {
// change phase.settings.plugins depending on req and phase.online/offline/visible
})
```phase has the following properties:
- visible, online, offline: booleans, purpose of the requesting phase
- settings: current phase settings
- policies: requesting phase policies
- location: parse url of the current phase```js
app.get('*.html', dom().route((phase, req, res) => {
if (phase.visible && req.query.url) {
// overwrite default location
location.href = req.query.url;
} else if (phase.online) {
res.type('html');
res.send('');
}
}));
```- `dom().route(dom.routers.png)` to setup png rendering
- see also [express-dom-pdf plugin](https://github.com/kapouer/express-dom-pdf)## Page settings and plugins
Plugins are asynchronous functions, executed in order.
```js
dom.plugins.fragment = async (page, settings, req, res) => {
settings.timeout = 30000;
page.on('idle', async () => {
const html = await page.evaluate(sel => {
return document.querySelector(sel)?.outerHTML;
}, req.query.fragment);
if (html) {
res.type('html');
res.send(html);
} else {
// html plugin will send page content
}
});
};
dom.online.plugins.delete('html').add('fragment').add('html');
app.get('*.html', dom(), express.static(app.get('views')));
````page` is a playwright page instance, with additional
`page.location`, a URL instance that can be modified
synchronously.## Bundled plugins
This is a limited list of plugins, some are used by default:
- console
Report browser console to node console.
Depends on settings.log value.- hidden
Force `document.visibilityState == "hidden"`.
Adds user stylesheet to keep rendering to minimum;
Honors `settings.hidden` boolean, if set by a previous plugin.- media
Sets `media` options, see [playwright doc](https://playwright.dev/docs/api/class-page#page-emulate-media).- cookies
If `settings.cookies` is true, copy all cookies,
else only copy cookies with names in this Set.
Defaults to an empty Set.- equivs
Parse `meta[http-equiv]` tags and set response headers accordingly.
Supports http-equiv="Status".
Removes the meta nodes, except when the names are listed in the
`settings.equivs` array.- languages
Pass current request `Accept-Language` to page route headers.
Sets `Content-Language` to the lang attribute found on documentElement.- preloads
Parse `link[rel=preload]` tags and set 'Link' response header.- referrer, referer
Sets headers.referer to express req.get('referrer')- redirect
catch navigation requests and instead sends a 302 redirection## Compatibility with caching proxies
express-dom currently uses `Sec-Purpose` request header, and set `Vary: Sec-Purpose` response headers, so all proxies should be okay with that.
## Logs
- `DEBUG=express-dom`
## Backend
express-dom installs playwright-core and expects a system-installed chrome browser to be available.
## License
MIT License, see LICENSE file.