To aid in the process of server-side rendering Joystick components, Joystick overrides the res.render()
function built into Express. Using this function, you can:
- Render a Joystick page component.
- Render a page component into a layout component.
- Pass route-specific props to a component.
- Define SEO metadata for a page.
- Define custom
<head>
and<body>
attributes.
Example Usage
Rendering a Component
/index.server.js
import joystick from '@joystick.js/node';
joystick.app({
routes: {
'/': (req = {}, res = {}) => {
return res.render('ui/pages/index/index.js');
},
},
});
In this example, Joystick renders the page component located at /ui/pages/index/index.js
. The server returns the component’s HTML and CSS.
Rendering into a Layout
/index.server.js
import joystick from '@joystick.js/node';
joystick.app({
routes: {
'/': (req = {}, res = {}) => {
return res.render('ui/pages/index/index.js', {
layout: 'ui/layouts/app/index.js',
});
},
},
});
Here, Joystick renders the page into a layout and passes the page as props.page
to the layout component.
Passing Props to a Component
/index.server.js
import joystick from '@joystick.js/node';
joystick.app({
routes: {
'/': async (req = {}, res = {}) => {
const active_sale = await process.databases.mongodb.collection('sales').findOne();
return res.render('ui/pages/index/index.js', {
layout: 'ui/layouts/app/index.js',
props: {
active_sale: !!active_sale,
},
});
},
},
});
Props defined in options.props
are passed to both the layout and the page.
Defining SEO Metadata
/index.server.js
import joystick from '@joystick.js/node';
joystick.app({
routes: {
'/': async (req = {}, res = {}) => {
return res.render('ui/pages/index/index.js', {
layout: 'ui/layouts/app/index.js',
head: {
title: 'A Custom SEO Title',
tags: {
meta: [
{ property: 'og:type', content: 'Website' },
{ property: 'og:site_name', content: 'Website Name' },
{ property: 'og:title', content: 'A Custom SEO Title' },
{ property: 'og:description', content: 'A custom Open Graph description.' },
{ property: 'og:image', content: 'https://mywebsite.com/seo/image.png' },
],
link: [
{ rel: 'stylesheet', href: '/styles/extra.css' },
],
script: [
{ src: '/scripts/extra.js', async: true },
],
style: [
{
attributes: {
id: 'custom-style',
media: 'screen',
},
content: `
body {
background-color: #f5f5f5;
}
`,
},
],
},
jsonld: {
'@context': 'https://schema.org/',
'@type': 'WebSite',
name: 'Website Name',
author: {
'@type': 'Organization',
name: 'Website Co.',
},
description: 'A custom JSON-LD description.',
},
},
});
},
},
});
SEO metadata like title
, meta
, link
, script
, style
, and JSON-LD can be added using the head
option.
Defining Custom Attributes
/index.server.js
import joystick from '@joystick.js/node';
joystick.app({
routes: {
'/': async (req = {}, res = {}) => {
return res.render('ui/pages/index/index.js', {
layout: 'ui/layouts/app/index.js',
attributes: {
head: {
class: {
list: ['no-js'],
},
},
body: {
class: {
list: ['is-index-page'],
},
},
},
});
},
},
});
Custom attributes for the <head>
and <body>
tags can be defined using the attributes
option.
Disable Escaping
Use With Caution
Escaping is turned on by default to protect your app from XSS (cross-site scripting) attacks. In some cases, it may be necessary to disable this conditionally. Make sure that no user data will flow through either the data or props (depending on which your disable escaping for) if you're going to disable escaping.
By default, Joystick automatically escapes any data and props sent to the client. If you'd like to disable this, you an do so on a per-render basis via res.render()
:
import joystick from '@joystick.js/node';
joystick.app({
routes: {
'/documentation/:slug': (req = {}, res = {}) => {
res.render('ui/pages/documentation/index.js', {
layout: 'ui/layouts/documentation/index.js',
props: {
docs: '<Assume an html string here...>',
},
escaping: {
props: false, // NOTE: Disable escaping only for props on this route.
},
})
},
},
})
This is useful for when you're rendering safe props/data (not user generated) via res.render()
.
API
Definition
res.render(page_path: string, options?: object) => void
Parameters
- page_path string required
- The path to the page component that should be rendered.
- options object
-
Additional options for rendering the page.
- layout string
-
Path to a layout component. The rendered page is passed as
props.page
. - props object
- Props to pass to the page and layout components.
- head object
-
Options for defining SEO metadata and custom tags in the <head>.
- title string
- The title for the page.
- tags object
-
Additional HTML tags to add to the <head>.
- meta array
- An array of objects representing HTML <meta> tags. Each object defines attributes and values for a meta tag.
- link array
- An array of objects representing HTML <link> tags. Each object defines attributes and values for a link tag.
- script array
- An array of objects representing HTML <script> tags. Each object defines attributes and values for a script tag.
- style array
-
An array of objects representing HTML <style> tags. Each object can define
attributes
(applied to the <style> tag) andcontent
(CSS rules as a string). The type is always set totext/css
automatically.
- jsonld object
- An object defining JSON-LD structured data for the page.
- attributes object
-
Custom attributes to add to the <head> or <body> tags.
- head object
-
Attributes for the <head> tag.
- class object
-
Options for adding class names to the <head> tag.
- list array
- An array of CSS class names to add.
- body object
-
Attributes for the <body> tag.
- class object
-
Options for adding class names to the <body> tag.
- list array
- An array of CSS class names to add.