I'm trying to utilize the SplitChunksPlugin to produce separate bundles per each page/template in a MPA. When I use the HtmlWebpackPlugin, I get an html file for each page with a script tag pointing to the correct bundle. That is great! However, the trouble I'm having is with my vendor files. I want separate html files to point to only the vendor bundles they need. I can't get each separate html file to point to the correct vendor bundles when the SplitChunksPlugin creates multiple vendor bundles. The bundles produced are:
home.bundle.js
product.bundle.js
cart.bundle.js
vendors~cart~home~product.bundle.js
vendors~cart~product.bundle.js
So basically the home template should reference home.bundle.js, vendors~cart~home~product.bundle.js, and not the second vendor bundle. Only the cart and product templates should reference both vendor bundles. I am utilizing the chunks option for the HtmlWebpackPlugin but can't get it to pull the correct vendor bundles unless I explicitly reference the name of it like so:
chunks: ['vendors~cart~home~product.bundle','home']
But this kinda defeats the purpose of dynamically rendering your script tags. I've tried creating a vendor entry point but this lumps all my vendors together. Is there some simple config I'm missing?
My webpack.config.js:
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const Visualizer = require('webpack-visualizer-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
home: './src/js/page-types/home.js',
product: './src/js/page-types/product.js',
cart: './src/js/page-types/cart.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist/js')
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
plugins: [
new CleanWebpackPlugin(['dist']),
new Visualizer(),
new HtmlWebpackPlugin({
filename: 'home.html',
chunks: ['vendors','home']
}),
new HtmlWebpackPlugin({
filename: 'product.html',
chunks: ['vendors','product']
}),
new HtmlWebpackPlugin({
filename: 'cart.html',
chunks: ['vendors~cart~product','cart']
}),
], ...
My js modules:
/* home.js */
import jQuery from 'jquery';
import 'bootstrap';
cart and product also reference the react library:
/* cart.js */
import jQuery from 'jquery';
import 'bootstrap';
import React from 'react';
import ReactDOM from 'react-dom';
/* product.js */
import jQuery from 'jquery';
import 'bootstrap';
import React from 'react';
import ReactDOM from 'react-dom';
Example html output home.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<script type="text/javascript" src="home.bundle.js"></script></body>
</html>
Use version4 of html-webpack-plugin (which is in beta now), and only include the entry chunk in the chunks option.
and
This will include related chunks automatically.
One option is to manually create your vendor chunks and then include whichever of those chunks needed for a page in the
chunks
option ofHtmlWebpackPlugin
.webpack.config.js:
The
vendor-all
chunk is to catch any other vendor libraries that are not included in the other chunks.