We are very happy to release version 4.0.0 of Podium. Both @podium/layout
and
@podium/podlet
are now available at v4.0.0.
Version 4.0.0 attempts to be almost entirely backwards compatible with version 3.0.0.
This release contains the following changes:
JSON Schema
The manifest which defines the contract between layouts and podlets are now defined using JSON Schema. The main reason for this is to cater for Podium implementations in languages other than Node.js.
Document template
This version introduces a concept we call a document template. A document template is intended to supply the necessary HTML for the page outside of the markup you need write to display your page content.
While a v4 ships with a default document template it's straight forward to build your own custom template and plug this into both layouts and podlets which helps make it easier to develop podlets in isolation (from layouts) while imposing the same constraints on it that it will have when included in a layout.
Please see the document template section for further information.
HTTP framework free
Originally Podium was bound to Express.js but with this release Podium is 100% HTTP framework free. It is even possible write Podium servers using only the core Node.js HTTP server module.
Having said this, Express.js is still first class in Podium which means it is still possible to use Podium in an Express.js server without anything more than the core Podium layout and podlet modules.
Besides supporting Express.js, Hapi and Fastify are supported through plugins maintained by the Podium team.
Serverless / cloud functions will also be supported in a future release.
Multiple assets support
It was previously only possible to set a single reference to JavaScript and CSS client side assets using a podlet's
.js()
and .css()
.
With version 4, it is now possible to call these methods multiple times to set multiple assets.
An additional type
field has also been added to the .js()
method making it possible to signal to layout servers
what type of JavaScript file are being specified.
Layout assets
The @podium/layout
module now has .js()
and .css()
methods which work the
same way as in @podium/podlet
. The intent is to be able to set client side assets
which are related specifically to the layout.
HttpIncoming replaces context argument
During the process of rewriting to HTTP framework free, an HttpIncoming
object was introduced which
is passed between the various parts of Podium.
You can read more about HttpIncoming
and its role here.
Due to this, you should pass an instance of HttpIncoming
(available at res.locals.podium
in express) to the .client.fetch()
and .client.stream()
methods in
a @podium/layout
instead of the context.
Previously Podium expected you to pass a Podium context to the fetch method like so:
app.get('/', (req, res) => {
const ctx = res.locals.podium.context;
const content = await podlet.fetch(ctx);
...
});
This will still work until Podium version 5 but it is expected that developers instead call fetch as follows:
app.get('/', (req, res) => {
const incoming = res.locals.podium;
const content = await podlet.fetch(incoming);
...
});
The context is part of HttpIncoming
.
The fetch method now resolves with a response object
When a Layout retrieves the content from a podlet it will now resolve with a response object instead of just the content as a string.
Previously calling .client.fetch()
would resolve with the content of a podlet as
a string:
app.get('/', (req, res) => {
const incoming = res.locals.podium;
const content = await podlet.fetch(incoming);
console.log(content); // <div> .... </div>
});
Now the fetch method with resolve with and object containing the podlet's content, css, js and headers:
app.get('/', (req, res) => {
const incoming = res.locals.podium;
const content = await podlet.fetch(incoming);
console.log(content); // {js: [], css: [], headers: {}, content: '<div> .... </div>'}
});
For backwards compabillity, using the response in a template literal or in string concatenation will result in the content value in the string. This will still work until Podium version 5.
app.get('/', (req, res) => {
const incoming = res.locals.podium;
const content = await podlet.fetch(incoming);
console.log(`${content}`); // <div> .... </div>
});
The .client.stream()
works as before, but there is now a beforeStream
event
which emits a response object:
app.get('/', (req, res, next) => {
const incoming = res.locals.podium;
const stream = component.stream(incoming);
stream.once('beforeStream', data => {
console.log(data); // {js: [], css: [], headers: {}, content: null}
});
stream.pipe(res);
});
State events
The .client
in @podium/layout
now has an extended state
event and .state
property can be used to determine what state a layout is in.
layout.client.on('state', state => {
console.log(state);
});
const podlet = layout.client.register({
uri: 'http://foo.site.com/manifest.json',
name: 'foo',
});
app.get('/', (req, res) => {
const incoming = res.locals.podium;
const content = await podlet.fetch(incoming);
...
});
The state provides information about the "podlet update life cycle". This is useful for determining when a podlet is being updated and when an update is complete or if a podlet is in an unhealty state.
Improved documentation
In the process of making Podium HTTP framework free and supporting multiple HTTP framework our documentation site has received some polish.
This site will now hold all documentation for end users of Podium and eventually it will have code examples reflecting all HTTP frameworks which are officially supported.
From now on, the documentation found in the README's in each module is to be considered documentation for developing Podium and not end user documentation.