You can check out this tutorial for a real world usage example, or read below for documentation.
In your webpack config file...
var StaticSiteGeneratorPlugin = require('static-render-webpack-plugin');
var routes = [
'/',
'/about',
'/projects', // regular routes
{ // routes as an object
path: '/not-found',
output: '/404.html'
}
];
module.exports = {
entry: ...,
output: {
filename: 'bundle.js',
path: ...,
// This is really important, the plugin expects the bundle output to export a function
libraryTarget: 'umd'
},
...
plugins: [
new StaticSiteGeneratorPlugin('bundle.js', routes)
]
};
This setup will generate
/index.html
/about/index.html
/projects/index.html
/404.html
This module takes the output of webpack's compilation process and expects it to export a function with 3 arguments
module.exports = function(path, props, callback) {
// Callback with the desired HTML string
callback(...)
}
StaticSiteGeneratorPlugin
is a constructor that takes up to 4 arguments.
new StaticSiteGeneratorPlugin(source, routes, props, watchFiles)
String
The route to the javascript file
Array<String|RouteObject>
An array of either string routes, ex. /
, /about
, /deep/route
. Or route objects, which follow this syntax:
{
path: String // ex, '/', '/about'
output: String // ex, '/404.html', '/deep/custom.file'
}
Any|Function
This property is passed to your javascript bundle as the 2nd parameter in the exported function. It can be anything.
If props is a function, the function is executed (with no parameters) every time a file needs to be rendered. This way, if you have static assets you want webpack to watch (markdown files, for instance), you can load them in with a function instead, and each time webpack compiles, the props will be different.
Array<String>?
This is optional. You can define an array of paths to files that you want the compiler to add to its dependencies. This way, when running webpack in watch mode, or webpack-dev-server, the files which are not in the javascript dependency tree will also be watched and can cause recompilation.
I use this to generate blog posts from .md files.
If you use React and React-Router, then your entry.js file might look something like this:
import React from 'react';
import Router from 'react-router';
import routes from './path/to/routes';
module.exports = function(path, props, callback) {
Router.run(routes, path, (Root) => {
const html = React.renderToString(<Root/>);
callback('<!doctype html>' + html);
});
}
if (typeof document != 'undefined') {
/**
* Running in a web environment, re-render the entire tree onto the document,
* react will be able to tell that what you are trying to render is exactly the same and
* adjust itself accordingly
*/
Router.run(routes, Router.HistoryLocation, (Root) => {
React.render(<Root/>, document);
});
}
Yes! This is possible. Look at this boilerplate project to see how: static-render-react-hot