Reputation: 31006
Is there a way to pre-generate the HTML structure of a (single route) React application directly in the HTML entry point?
Then the page will be able to display HTML (based on React initial state) before any JS is loaded.
I'm actually using webpack-html-loader but any other loader or plugin is welcome ;)
PS: May static-site-generator-webpack-plugin be of any help?
PS: I'm not using React Router
Upvotes: 14
Views: 5390
Reputation: 2403
Here you have a working example https://github.com/aganglada/preact-minimal/blob/master/config/webpack.config.js, if you like you can fork it and take a look at how this work all together.
Hope it helps :)
Upvotes: 0
Reputation: 1924
Jekyll is great static site generator which can be extended with custom ruby plugins. You need to enable WebPack to make Jekyll calls. See Plugging Webpack to Jekyll Powered Pages
Upvotes: 0
Reputation: 3260
If you want to use static-site-generator-webpack-plugin you first need to build a bundle with webpack bundle.js
that exports a render function that takes following arguments.
locals
an object with various page metadata e.g. title
that go into component parameters (traditionally thought of as template variables).callback
a nodejs style (err, result)
callback that you will call with your rendered html as the value for result
e.g.
// entry.js, compiled to bundle.js by webpack
module.exports = function render(locals, callback) {
callback(null,
'<html>' + locals.greet + ' from ' + locals.path + '</html>');
};
It is in this function that you will instantiate your components (possibly via React Router if you want) and render them with ReactDOMServer.renderToString()
.
You will then specify the compiled bundle.js
as bundle
in your instantiation of StaticSiteGeneratorPlugin
as well as your concrete routes in paths
and in locals
an object containing the above mentioned metadata values.
var paths, locals; // compute paths from metadata files or frontmatter
module.exports = {
entry: {
bundle: './entry.js' // build bundle.js from entry.js source
},
...,
plugins: [
new StaticSiteGeneratorPlugin('bundle', paths, locals)
]
}
The keys you specify for locals
in webpack.config.js
in will be present in the locals
parameter of every call to render(locals, callback)
. They will be merged with path
, assets
and webpackStats
keys provided by the plugin.
If you want to load javascript code into your pages after rendering you could compile an additional page.js
entry to your webpack config that calls ReactDOM.render()
in the typical manner and then load that bundle in a script
tag emitted by in your render(locals, callback)
function in your bundle.js
(above). Ensure that page.js
mounts components to the same location in the DOM as they are when rendered by entry.js
(you will probably set an id
attribute on the parent element). You will also need to ensure that any location (i.e. route path) dependent variables align in both environments.
Check out the source code of Gatsby which also uses this plugin. You can also have a look at the source code for Phenomic for an alternative approach.
Upvotes: 10
Reputation: 260
You should try server side rendering, it will let react render the first view of your app in a backend and deliver a static HTML. This boilerplate already comes with server rendering set up and you can learn more about it here
Upvotes: 2