Fastify HTM Preact Views
Render Preact views via HTM in Fastify applications.
This offers a compilation-free views with Preact as a Fastify plugin. See "alternatives to JSX" in the Preact docs to learn more about why you might do this.
Table of Contents
Requirements
This library requires the following to run:
Usage
Install with npm (you'll also need to install Preact alongside this module):
npm install preact @rowanmanning/fastify-htm-preact-views
Register the plugin before your routes in your Fastify application, using a require
call:
const app = require('fastify')();
app.register(require('@rowanmanning/fastify-htm-preact-views'));
app.get('/', (request, reply) => {
reply.view('example', {
thing: 'World'
});
});
app.listen(8080);
In the above example, you'll need to provide a view in <CWD>/views/example.js
:
module.exports = ({html, thing}) => {
return html`
<h1>Hello ${thing}!</h1>
`;
};
In all views, the html
prop is an htm
tagged template function, pre-bound to Preact.
App-wide properties
You can specify a default set of global properties as an option when you register the plugin:
app.register(require('@rowanmanning/fastify-htm-preact-views'), {
defaultProps: {
thing: 'World'
}
});
Now when you render a view, you can override this default property or don't supply props and it will fall back to the default. Using the example
view defined above:
// Renders "Hello World" because it falls back to the default
app.get('/1', (request, reply) => {
reply.view('example');
});
// Renders "Hello Friend"
app.get('/2', (request, reply) => {
reply.view('example', {
thing: 'Friend'
});
});
Reply properties
You can specify additional properties on a reply object, which will be available to later routes:
app.addHook('preHandler', (request, reply, done) => {
reply.props = {
thing: 'Friend'
};
done();
});
// Renders "Hello Friend"
app.get('/', (request, reply) => {
reply.view('example');
});
Layouts and partials
You can wrap views in a layout by defining a Preact component in a new file and requiring it in. Partials can be required in the same way and used like you would any shared component.
In views/layouts/default.js
, define the layout:
module.exports = ({children, html, title}) => {
return html`
<html>
<head>
<title>${title}</title>
</head>
<body>
${children}
</body>
</html>
`;
};
In views/example.js
, load it in and wrap content in it. You'll need to pass props through:
const Layout = require('./layouts/default');
module.exports = props => {
const {html, thing} = props;
return html`
<${Layout} ...${props}>
<h1>Hello ${thing}!</h1>
</>
`;
};
Changing the doctype and content-type
By default, an HTML5 doctype is send with the rendered output, and the Content-Type
header is set to text/html
. These are both configurable as props passed into reply.view
.
app.get('/', (request, reply) => {
reply.view('example', {
doctype: '<?xml version="1.0" encoding="UTF-8"?>',
contentType: 'text/xml'
});
});
Both of these properties can be set to a falsy value, which means they will not be sent with the response.
Config options
This plugin can configured using options passed into the Fastify register
function:
app.register(require('@rowanmanning/fastify-htm-preact-views'), {
// Options go here
});
The available options are:
-
defaultProps
:Object
. An object containing default application-wide properties. -
viewsFolder
:String
. The folder to look for view files in. Defaults to<CWD>/views
. -
prettyOutput
:Boolean
. Whether to output pretty HTML. Defaults totrue
.
Contributing
The contributing guide is available here. All contributors must follow this library's code of conduct.
License
Licensed under the MIT license.
Copyright © 2021, Rowan Manning.