diff --git a/README.md b/README.md index 7e198cc..db7ecbb 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,42 @@ # html-render-webpack-plugin -webpack plugin for rendering static HTML in a multi-config webpack build +webpack plugin for rendering static HTML in a multi-config webpack build. + +`html-render-webpack-plugin` is applied to a webpack [MultiCompiler](https://webpack.js.org/configuration/configuration-types/#exporting-multiple-configurations) to enable rendering based on all resulting webpack outputs. + +The render build's code is used to generate the HTML, often using values from other builds such as asset names. + +For example, you may wish to add a script tag where the name includes a hash: +**src/render.js** + +```js +export default ({ assetsByChunkName }) => { + return ` + + + +`; +}; +``` + +**dist/index.html** + +```html + + + + + +``` + +See [the full example below](#example-client-assets). # Setup **Note:** Requires Node v10.12 or greater. +Install the plugin. + ```bash $ npm install webpack html-render-webpack-plugin # OR @@ -18,15 +49,12 @@ Export [multiple webpack configurations](https://webpack.js.org/configuration/co // webpack.config.js module.exports = [ { - name: "client", - target: "web" - // Creates files that run on the browser + name: "render", + target: "node" // Creates assets that render HTML that runs well in node }, { - name: "render", - target: "node" - // Creates assets that render HTML that runs well in node - dependencies: ["client"], // Requires client files to be ready before render + name: "client", + target: "web" // Creates files that run on the browser } ]; ``` @@ -70,46 +98,20 @@ server.listen(8080, "localhost", () => {}); See [examples](#examples) for more details. -## Why two configurations? It's all just JavaScript - -For some builds you may be able to avoid needing two configurations. If that is the case you don't need this tool and can avoid the complexity. -Here are some reasons I've needed to use two configurations: - -##### Complex loaders - -Some projects use webpack only to generate the client assets. For the render they then use tools such as babel directly. -This can become a complex when the project has webpack loaders that affect the behaviour of the code such as [CSS Modules](https://github.com/css-modules/css-modules). This can result in differences between rendered HTML and client code. - -##### Async chunks - -webpack's `target` field helps webpack decide how to handle async chunks. -For example: - -- A web build may try to create ` + + `; +}; +``` + +**webpack.config.js** + +```js +module.exports = [ + { + name: "client", + target: "web", + output: { + filename: "client-[name]-[contenthash].js", + } + entry: { main: path.resolve("src", "client.js") } + }, + { name: "render", target: "node", output: { @@ -238,7 +321,10 @@ module.exports = function getCompiler({ liveReload, mode }) { compiler.apply( new RenderStaticPlugin({ routes, - mapStatsToParams: ({ clientStats }) => { + mapStatsToParams: ({ webpackStats }) => { + const clientStats = webpackStats + .toJson() + .children.find(({ name }) => name === "client"); const fileSystem = compiler.compilers[0].outputFileSystem.readFileSync ? compiler.compilers[0].outputFileSystem : fs; @@ -335,7 +421,6 @@ module.exports = ({ liveReload, mode }) => { ] }), merge(common, { - dependencies: ["client"], output: { libraryExport: "default", library: "static", @@ -349,3 +434,30 @@ module.exports = ({ liveReload, mode }) => { ]; }; ``` + +## Why two configurations? It's all just JavaScript + +For some builds you may be able to avoid needing two configurations. If that is the case you don't need this tool and can avoid the complexity. +Here are some reasons I've needed to use two configurations: + +##### Complex loaders + +Some projects use webpack only to generate the client assets. For the render they then use tools such as babel directly. +This can become a complex when the project has webpack loaders that affect the behaviour of the code such as [CSS Modules](https://github.com/css-modules/css-modules). This can result in differences between rendered HTML and client code. + +##### Async chunks + +webpack's `target` field helps webpack decide how to handle async chunks. +For example: + +- A web build may try to create `