I am trying to separate my vendor and app packages with the autodll-webpack-plugin (v0.4.2
). this package is a top level plugin over the DllPlugin of webpack and the add-asset-html-webpack-plugin for auto-ordering the imports in the index.html
.
What this plugin should do is separating the vendor libraries and the app code. I could do this with the CommonsChunkPlugin from webpack, but that way the bundle is regenerated on every recompile. Which is less efficient then generating the vendor bundle once and only recompile it when a lib has been changed.
The problem
I got this plugin to "work" (it is outputting a vendor.bundle.js
). The only problem here is that when I inspect the app.bundle.js
with webpack-bundle-analyzer (v2.13.1
). I can see that all the node_modules that are in the vendor.bundle.js
are also loaded into this bundle, thus the plugin is not working correctly.
Versions
I am using:
v4.11.0
v7.1.4
v6.26.3
v0.4.2
Project structure
My project has the following document structure:
App
-- build //Here are the output bundles located
-- node_modules
-- public
-- index.html
-- src // App code
-- webpack
-- webpack.common.js
-- webpack.dev.js
-- webpack.prod.js
-- package.json
My webpack.common.js (This code is shared with the Dev & prod builds)
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AutoDllPlugin = require('autodll-webpack-plugin');
module.exports = {
entry: {
app: [
'babel-polyfill',
'./src/index.js',
],
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, '../build'),
publicPath: '', // Is referenced by the autodll-webpack-plugin
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
plugins: ['react-hot-loader/babel'],
cacheDirectory: true,
presets: ['env', 'react'],
},
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html'
}),
new AutoDllPlugin({
inject: true, // will inject the DLL bundle to index.html
debug: false,
filename: '[name]_[hash].js',
context: path.join(__dirname, '..'),
path: '',
entry: {
vendor: [
'react',
'react-dom'
]
},
}),
],
};
According to the docs of the autodll-webpack-plugin
the context key should be used for separating. So I think this is where the problem lies.
The docs describe that you should reference the folder where the webpack.config.js
is, but I have 3 of them, which one do I need to reference? And my folder is called webpack
and not config
that you see in the docs, is ..
also correct here?
So in the end I didn't get the DLL setup to work. After reading some more I realized that the creator of the autodll-webpack-plugin advises to use the hard-source-webpack-plugin instead, because webpack is possibly going to use as a default option this in the future.
After reading some more I also realized that it is not advised to use the DLL plugin in production, since you have to recompile it anyways (dev build adds stuff). So you should use the hard-source-webpack-plugin
for the dev build and the SplitChunksPlugin for production.
I got these two to work quite easily:
Webpack.dev.js
const merge = require('webpack-merge');
const webpack = require('webpack');
const path = require('path');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
hot: true,
contentBase: path.resolve(__dirname, 'build'),
historyApiFallback: true, // Allow refreshing of the page
},
plugins: [
// Enable hot reloading
new webpack.HotModuleReplacementPlugin(),
// Enable caching
new HardSourceWebpackPlugin({
cacheDirectory: '.cache/hard-source/[confighash]',
configHash: function(webpackConfig) {
return require('node-object-hash')({ sort: false }).hash(webpackConfig);
},
environmentHash: {
root: process.cwd(),
directories: [],
files: ['package-lock.json'],
},
info: {
mode: 'none',
level: 'warn',
},
}),
],
});
webpack.prod.js
const merge = require('webpack-merge');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CleanWebpackPlugin = require('clean-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
plugins: [
// Clean the build folders
new CleanWebpackPlugin(['build'], {
root: process.cwd(), // Otherwise the 'webpack' folder is used
}),
//Make vendor bundle size visible
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'stats/prod-report.html',
}),
],
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
name: 'vendor',
chunks: 'all',
test: /[\\/]node_modules[\\/]/,
},
},
},
minimizer: [
// Optimize minimization
new UglifyJsPlugin({
cache: true,
parallel: true,
uglifyOptions: {
ecma: 6,
mangle: true,
toplevel: true,
},
}),
],
},
});
I hope this helps anyone.