We'd like to have two outputs from Webpack - our entire app with all of its dependencies, and a single different page with only one dependency (that isn't shared by the main app).
It seems the way to do this is to leverage the entry
property of a Webpack config. However, that's not enough, as we also use HtmlWebpackPlugin to output our HTML file with the build.js
that Webpack compiled dynamically added (as well as compiled LESS, etc). According to the HtmlWebpackPlugin docs:
If you have multiple Webpack entry points, they will all be included
with script tags in the generated HTML.
That won't work for us, so I need to leverage their filterChunks
option. This GitHub issue response states it most succinctly:
module.exports = {
entry: {
'page1': './apps/page1/scripts/main.js',
'page2': './apps/page2/src/main.js'
},
output: {
path: __dirname,
filename: "apps/[name]/build/bundle.js"
},
plugins: [
new HtmlWebpackPlugin({
inject: false,
chunks: ['page1'],
filename: 'apps/page1/build/index.html'
}),
new HtmlWebpackPlugin({
inject: false,
chunks: ['page2'],
filename: 'apps/page2/build/index.html'
})
]
};
(in the HtmlWebpackPlugin docs, this is under the "filtering chunks" section)
So, I modified our code like so:
module.exports = {
entry: {
app: './public/js/ide.js',
resetPassword: './public/js/reset_password.js'
},
output: {
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
publicPath: '/'
},
...
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app']
}),
new HtmlWebpackPlugin({
filename: 'reset_password.html',
template: 'public/html/reset_password.html',
inject: true,
chunks: ['resetPassword']
}),
],
}
Now, when I rebuild the project (just trying with WebpackDevServer for now) and navigate to /index.html
, I can see in the network tab the massive bundle file, the contents of index.html
(based off the ide.html
template), as well as requests for various external resources. However, no actual JavaScript will run (say, a console.log in ide.js
). All the HTML in the file shows.
For reset_password.html
, all HTML shows, and the reset_password.js
file shows, but none of the javascript within runs.
How can I ensure the JavaScript in my entry
files runs?
EDIT: I have gotten ide.js
working, because I hadn't realized the following was a "chunk":
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\/]node_modules[\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
So, I added vendor
to the index.html
HtmlWebpackPlugin chunks
property. Now, it looks like this:
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app', 'vendor']
}),
reset_password
doesn't need anything in the node_modules folder, and this also doesn't explain why no JavaScript at all would run inside of ide.js
, so I'm still quite confused. Also, reset_password
is still non-functional.
EDIT2: Looking through the apparently attached reset_password.js
file when I load reset_password.html
, I can see this line
eval("
console.log('DRAGONHELLO');//# sourceURL=[module]
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9wdWJsaWMvanMvcmVzZXRfcGFzc3dvcmQuanM/ZjY5ZSJdLCJuYW1lcyI6WyJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiOztBQUNBQSxRQUFRQyxHQUFSLENBQVksYUFBWiIsImZpbGUiOiIuL3B1YmxpYy9qcy9yZXNldF9wYXNzd29yZC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc29sZS5sb2coJ0RSQUdPTkhFTExPJylcbiJdLCJzb3VyY2VSb290IjoiIn0=
//# sourceURL=webpack-internal:///./public/js/reset_password.js
");
So, clearly my console.log('DRAGONHELLO')
is "seen", but I have no idea why it isn't running.
EDIT3: Adding vendor
to chunks
for reset_password.html
causes the JavaScript to run, but I have no idea why, and this is non-ideal because the whole point of the exercise was to have two different bundles, one which was very minimal and didn't need all of our node_modules
.
EDIT4: I ran Webpack with profile:true
, and I can see I'm not getting the "Chunk Names" wrong:
js/app.3d18b43294ebd54ed083.js 1.34 MiB 0 [emitted] [big] app
js/resetPassword.198485be2b163cc258ed.js 1.02 KiB 1 [emitted] resetPassword
js/2.e7f92193ea3c611a0b36.js 2.23 MiB 2 [emitted] [big] vendor
js/app.3d18b43294ebd54ed083.js.map 2.71 MiB 0 [emitted] app
js/resetPassword.198485be2b163cc258ed.js.map 4.57 KiB 1 [emitted] resetPassword
js/2.e7f92193ea3c611a0b36.js.map 7.12 MiB 2 [emitted] vendor
EDIT5: I tried both
module.exports = {
//...
optimization: {
runtimeChunk: {
name: entrypoint => `runtime~${entrypoint.name}`
}
}
};
and
module.exports = {
//...
optimization: {
runtimeChunk: true
}
};
Based on PlayMa256's comment and the webpack docs on runtimeChunk. Neither caused the JavaScript to execute.
See Question&Answers more detail:
os