html-webpack-prerender-plugin allows for several configuration shorthands. We'll explain the component parts of each, but these are all equivalent configurations:
new HtmlWebpackPrerenderPlugin({ main: '#root' });new HtmlWebpackPrerenderPlugin({
'index.html': {
main: '#root',
},
});new HtmlWebpackPrerenderPlugin({
'index.html': {
main: {
selector: '#root',
scope: {},
props: {},
injectPropsTo: false,
},
}
});Let's breakdown the parts of the innermost configuration object, the rendering context object.
new HtmlWebpackPrerenderPlugin({
'index.html': {
main: { // 👇 Rendering context object
selector: '#root',
scope: {},
props: {},
injectPropsTo: false,
},
}
});A CSS selector for the container your app will be rendered into. For example, a template like this...
<body>
<div id='my-app'></div>
</body>... and a configuration like this ...
{
selector: '#my-app',
}... will render like this ...
<body>
<div id='my-app'>
<!-- Your app markup will be rendered here. -->
</div>
</body>Keep in mind the plugin will remove any children from this container your selector grabs before injecting your rendered markup, so generally it's a bad idea to use the body tag. Instead, supply a template to html-webpack-plugin that includes a custom root container node for your app.
An object that will be added to the globals when evaluating your app code in a node context. By default scope will include jsdom window and document instances:
const { window } = new JSDOM(templateHTML);
const { document } = window;
const scope = { window, document };You can also use it to add any necessary context to make your script work in both a browser and node context:
const requestAnimationFrame = require('raf');
module.exports = {
// ...
plugins: [
// ...
new HtmlWebpackPrerenderPlugin({
main: {
selector: '#root',
scope: { requestAnimationFrame },
},
}),
]
};An object passed to your app's default render function. For example, a configuration like this...
{
props: { title: 'My title'},
}... and an app like this ...
export default (props) => `<h1>${props.title}</h1>`;... will render like this ...
<h1>My title</h1>This string will be used to create a global variable in your app that will contain the value of your props, which is useful when hydrating a dynamic app with a preloaded state. For example, this setup...
{
props: { title: 'My title' },
injectPropsTo: '__PRELOADED_STATE__',
}... will render and inject this script tag into your page ...
<script>
window.__PRELOADED_STATE__ = { title: 'My title'};
</script>Outside the rendering context, pointer properties tell the plugin what and where to inject your app.
new HtmlWebpackPrerenderPlugin({
// 👇 Filename pointer
'index.html': {
// 👇 Entry pointer
main: { ... },
}
});The entry pointer points at a specific entry for the the app the plugin will render and inject into your page.
By default, your entry is main...
module.exports = {
entry: './js/index.js',
// ...
plugins: [
// ...
new HtmlWebpackPrerenderPlugin({
'index.html': {
// 👇 Default entry name
main: '#root',
}
}),
],
};... but you can use this to select specific chunks ...
module.exports = {
entry: {
app: './js/index.js',
someOtherApp: './js/other.js',
},
// ...
plugins: [
// ...
new HtmlWebpackPrerenderPlugin({
'index.html': {
// 👇 Entry chunk name
app: '#root',
}
}),
],
};Tells the plugin what page to inject the app into. This should be the same as filename property used in html-webpack-plugin. For example:
[
new HtmlWebpackPlugin({
filename: 'cutom-page-name.html',
template: './templates/index.html',
}),
new HtmlWebpackPrerenderPlugin({
'custom-page-name.html': { main: '#root' }
}),
]And like in html-webpack-plugin, you can omit the filename pointer and it will be assumed to be index.html.
[
new HtmlWebpackPlugin({
template: './templates/index.html',
}),
new HtmlWebpackPrerenderPlugin({ main: '#root' }),
]You can also use this property to skip pages in your compilation.
[
new HtmlWebpackPlugin({
filename: 'about.html',
template: './templates/about.html',
}),
new HtmlWebpackPlugin({
filename: 'page.html',
template: './templates/index.html',
}),
new HtmlWebpackPrerenderPlugin({
'page.html': { main: '#root' }
}),
]In combination, these pointers can be used to create complex configurations. For example, this configuration will render 3 apps in 2 pages, with a page specific app and a header on each page.
module.exports = {
entry: {
aboutApp: './js/about/index.js',
pageHeader: './js/header/index.js',
pageApp: './js/page/index.js',
},
// ...
plugins: [
new HtmlWebpackPlugin({
filename: 'page.html',
template: './templates/page.html',
excludeChunks: ['aboutApp'],
}),
new HtmlWebpackPlugin({
filename: 'about.html',
template: './templates/about.html',
excludeChunks: ['pageApp'],
}),
new HtmlWebpackPrerenderPlugin({
'about.html': {
aboutApp: '#app-root',
pageHeader: {
selector: '#header-root',
props: { activePage: 'about' },
},
},
'page.html': {
pageApp: '#app-root',
pageHeader: {
selector: '#header-root',
props: { activePage: 'page' },
},
}
}),
],
};