Skip to main content

Version 4.0.0

· 5 min read
Trygve Lie

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.