Podlet
Module for building podlet servers. A podlet server serves page fragments.
Install / Use
/learn @podium-lib/PodletREADME
@podium/podlet v5
A Module for building page fragment servers in a micro frontend architecture.
See the official Podium documentation site.
This is a module for building a podlet server. A podlet server is responsible for generating HTML fragments which can then be used in a [@podium/layout] server to compose a full HTML page.
This module can be used together with a plain node.js HTTP server or any HTTP framework and any templating language of your choosing (or none if you prefer).
Note: Connect compatible middleware based frameworks (such as [Express]) are considered
first class in Podium so this module provides a .middleware() method for
convenience.
For writing podlet servers with other HTTP frameworks, the following modules also exist:
- [Fastify Podlet Plugin]
Installation
$ npm install @podium/podlet
Getting started
Building a simple podlet server using [Express].
import express from 'express';
import Podlet, { html } from '@podium/podlet';
// create a new podlet instance
const podlet = new Podlet({
name: 'myPodlet',
version: '1.3.1',
pathname: '/',
development: true,
});
// create a new express app instance
const app = express();
// mount podlet middleware in express app
app.use(podlet.middleware());
// create a route to serve the podlet's manifest file
app.get(podlet.manifest(), (req, res) => {
res.json(podlet);
});
// create a route to serve the podlet's content
app.get(podlet.content(), (req, res) => {
res.podiumSend(html`<div>hello world</div>`);
});
// start the app on port 7100
app.listen(7100);
API Documentation
Constructor
Create a new podlet instance.
const podlet = new Podlet(options);
options
| option | type | default | required |
| ------------ | --------- | ---------------- | -------- |
| name | string | | ✓ |
| version | string | | ✓ |
| pathname | string | | ✓ |
| manifest | string | /manifest.json | |
| content | string | / | |
| fallback | string | | |
| logger | object | | |
| development | boolean | false | |
| useShadowDOM | boolean | false | |
name
The name the podlet identifies itself by. This value can contain upper and lower case letters, numbers, the - character and the _ character. No spaces.
When shadow DOM is used, either via the useShadowDOM constructor option or via the wrapWithShadowDOM method, the name must comply with custom element naming rules.
See MDN for more information.
Example:
const podlet = new Podlet({
name: 'myPodlet';
});
version
The current version of the podlet. It is important that this value be updated when a new version of the podlet is deployed since the page (layout) that the podlet is displayed in uses this value to know whether to refresh the podlet's manifest and fallback content or not.
Example:
const podlet = new Podlet({
version: '1.1.0';
});
pathname
Pathname for where a Podlet is mounted in an HTTP server. It is important that this value matches where the entry point of a route is in an HTTP server since this value is used to define where the manifest is for the podlet.
If the podlet is mounted at the "root", set pathname to /:
const app = express();
const podlet = new Podlet({
name: 'myPodlet',
version: '1.0.0',
pathname: '/',
});
app.use(podlet.middleware());
app.get('/', (req, res, next) => {
[ ... ]
});
If the podlet is to be mounted at /foo, set pathname to /foo and mount
middleware and routes at or under /foo
const app = express();
const podlet = new Podlet({
name: 'myPodlet',
version: '1.0.0',
pathname: '/foo',
});
app.use('/foo', podlet.middleware());
app.get('/foo', (req, res, next) => {
[ ... ]
});
app.get('/foo/:id', (req, res, next) => {
[ ... ]
});
manifest
Defines the pathname for the manifest of the podlet. Defaults to /manifest.json.
The value should be relative to the value set on the pathname argument. In
other words if a Podlet is mounted into an HTTP server at /foo and the
manifest is at /foo/component.json, set pathname and manifest as follows:
const app = express();
const podlet = new Podlet({
name: 'myPodlet',
version: '1.0.0',
pathname: '/foo',
manifest: '/component.json',
});
app.get('/foo/component.json', (req, res, next) => {
[ ... ]
});
The value can be a relative URL and the .manifest() method can be used to
retrieve the value after it has been set.
content
Defines the pathname for the content of the Podlet. Defaults to /.
The value should be relative to the value set on the pathname argument. In
other words if a podlet is mounted into an HTTP server at /foo and the
content is at /foo/index.html, set pathname and content as follows:
const app = express();
const podlet = new Podlet({
name: 'myPodlet',
version: '1.0.0',
pathname: '/foo',
content: '/index.html',
});
app.get('/foo/index.html', (req, res, next) => {
[ ... ]
});
The value can be a relative or absolute URL and the .content() method can be used to retrieve the value after it has been set.
fallback
Defines the pathname for the fallback of the Podlet. Defaults to an empty string.
The value should be relative to the value set with the pathname argument. In
other words if a Podlet is mounted into an HTTP server at /foo and the
fallback is at /foo/fallback.html, set pathname and fallback as follows:
const app = express();
const podlet = new Podlet({
name: 'myPodlet',
version: '1.0.0',
pathname: '/foo',
fallback: '/fallback.html',
});
app.get('/foo/fallback.html', (req, res, next) => {
[ ... ]
});
The value can be a relative or absolute URL and the .fallback() method can be
used to retrieve the value after it has been set.
logger
Any log4j compatible logger can be passed in and will be used for logging. Console is also supported for easy test / development.
Example:
const podlet = new Podlet({
logger: console;
});
Under the hood [abslog] is used to abstract out logging. Please see [abslog] for further details.
development
Turns development mode on or off. See the section about development mode.
useShadowDOM
Turns declarative shadow DOM encapsulation on for the podlet. When enabled, the podlet content will be wrapped inside a declarative shadow DOM wrapper to isolate it from the rest of whichever page it is being included on.
const podlet = new Podlet({ ..., useShadowDOM: true });
Please note the following caveats when using this feature:
- You must name your podlet following custom element naming conventions as explained here: https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names
- In order to style your content, you will need to include your CSS inside the shadow DOM wrapper. You can do this using one of the following 2 options:
You can include a <style> tag before your content
res.podiumSend(html`
<style>
...styles here...
</style>
<div>...content here...</div>
`);
You can have your podlet CSS included for you by using the "shadow-dom" scope
podlet.css({ value: '/path/to/css', scope: 'shadow-dom' });
res.podiumSend(html`
<div>...content here...</div>
`);
For more fine grained control, you can use the podlet.wrapWithShadowDOM method directly
const podlet = new Podlet({ ..., useShadowDOM: false });
const wrapped = podlet.wrapWithShadowDOM(`<div>...content here...</div>`);
res.podiumSend(`
${wrapped}
`);
Podlet Instance
The podlet instance has the following API:
.process(HttpIncoming, options)
Method for processing a incoming HTTP request. This method is intended to be used to implement support for multiple HTTP frameworks and in most cases will not need to be used directly by library users to create podlet servers.
What it does:
- Handles detection of development mode and sets appropriate defaults
- Runs context deserializing on the incoming request and sets a context object at
HttpIncoming.context.
Returns an [HttpIncoming] object.
The method takes the following arguments:
HttpIncoming (required)
An instance of the [HttpIncoming] class.
import { HttpIncoming } from '@podium/utils';
import Podlet from '@podium/podlet';
const podlet = new Podlet({
name: 'myPodlet',
version: '1.0.0',
pathname: '/',
});
app.use(async (req, res, next) => {
const incoming = new HttpIncoming(req, res, res.locals);
try {
await podlet.process(incoming);
if (!incoming.proxy) {
res.locals.podium = result;
next();
}
} catch (error) {
next(error);
}
});
options
| option | default | type | required | details |
| ------ | ------- | --------- | -------- | ----------------------------------------------------------------------- |
| proxy | true | boolean | false | If @podium/proxy should be applied as part of the .process() method |
.middleware()
A Connect compatible middleware function which takes care of the multiple
operations needed for a podlet to operate correctly. This function is more or less a wrapper for
the .process()
