const config = {
entry:{
'datalocation': __dirname + '/src/datalocation.js',
'reposerver': __dirname + '/src/reposerver.js'
},
optimization:{
splitChunks: {
chunks:'all',
name:false
}
},
plugins:[
new HTMLWebpackPlugin({
template: __dirname + '/src/index.html',
chunks: [*** How to autofill the optimized generated chunks for this entry + only the entry chunk, that will be 0.js + datalocation.js as per webpack. I dont want to include repocenter.js ]
filename: datalocation.html',
inject: 'body'
}),
new HTMLWebpackPlugin({
template: __dirname + '/src/index.html',
chunks: [*** How to autofill the optimized generated chunks for this entry + only the entry chunk, that will be 0.js + repocenter.js as per webpack. I dont want to include datalocation.js ]
filename: reposerver.html',
inject: 'body'
}),
]
}
In HTMLWebpaclPlugin under chunks, How to autofill the optimized generated chunks for this entry + only the entry chunk,
The output of web pack
Entrypoint datacenter = 0.js datalocation.js
Entrypoint reposerver = 0.js reposerver.js
In this example there is only one common module, we may have many common modules for a large project with a different set of optimized common modules for each entry
This is similar to #882, but it was closed un resolved.
878 works only for a single entry or it includes all optimized chunks in all html pages
You are right #882 seems to be not exactly the same as #878.
Sorry @yqz0203 I just thought it's only about split chunks.
@bemineni Right now the feature you are talking about is not available.
We would have to find out:
0.js as an entry module or as an child of datalocation.jsdatalocation.js and 0.js is knownCould you please take a look at that?
I am new to web pack, will try to look into, but I cannot guarantee it. I have a busy schedule with my current bread and butter job.
No problem - I am also very busy so there is no hurry to solve this issue.
You could try to use excludeChunks?
new HTMLWebpackPlugin({
template: __dirname + '/src/index.html',
excludeChunks: ['reposerver'],
filename: 'datalocation.html',
inject: 'body'
}),
new HTMLWebpackPlugin({
template: __dirname + '/src/index.html',
excludeChunks: ['datalocation'],
filename: 'reposerver.html',
inject: 'body'
}),
@schmkr . We still need to figure out on how to get the optimized chunks to include in the HTML
The one solution I found it's create two separate build for each entry points and run it separately.
I have two builds one for production which generates main index.html with bundles and one for login page.
"build": "webpack --progress --config webpack/prod.js && webpack --progress --config webpack/login.js && cpx \"dist/**/*\"
I had to solve a similar problem for a project I'm working on. We build multiple pages, each with a single entrypoint and one HtmlWebpackPlugin instance to generate the HTML page, while sharing some JS modules and stylesheets between them.
I wanted to let Webpack determine how to split the chunks and pass the dynamically generated chunk names to each HtmlWebpackPlugin instance. I've achieved that with a custom plugin and piggybacking the entrypoint name on the HtmlWebpackPlugin options:
class ChunksFromEntryPlugin {
apply(compiler) {
compiler.hooks.emit.tap("ChunksFromEntryPlugin", compilation => {
const stats = compilation.getStats().toJson();
compilation.hooks.htmlWebpackPluginAlterChunks.tap(
"ChunksFromEntryPlugin",
(_, { plugin }) => {
// takes entry name passed via HTMLWebpackPlugin's options
const entry = plugin.options.entry;
return stats.entrypoints[entry].chunks.map(id =>
stats.chunks.find(chunk => chunk.id === id)
);
}
);
});
}
}
Webpack config:
module.exports = {
entry: {
login: 'apps/login.js',
// some more entries
},
plugins: [
new HtmlWebpackPlugin({
// `chunks` will be replaced by the "ChunksFromEntryPlugin" below
chunks: [],
entry: 'login',
/* other options */
}),
new ChunksFromEntryPlugin()
]
};
This implementation still feels quite clunky to me but it works for us. Could this be a good starting point to resolve this issue?
@dmarku wow that's good to know!
According to your example the information available in the webpack emit phase
compilation.getStats() is quite slow.
Could you please check if it is also part of compilation.entrypoints ?
Yes, the compilation object provides all the information needed to generate the chunks. However, when returning the modified chunks array I had to emulate the properties of the JSON stats in order to make it work.
The variant I've successfully tried today:
```.js
class ChunksFromEntryPlugin {
apply (compiler) {
compiler.hooks.emit.tap('ChunksFromEntryPlugin', compilation => {
compilation.hooks.htmlWebpackPluginAlterChunks.tap(
'ChunksFromEntryPlugin',
(_, { plugin }) => {
// takes entry name passed via HTMLWebpackPlugin's options
const entry = plugin.options.entry;
const entrypoint = compilation.entrypoints.get(entry);
return entrypoint.chunks.map(chunk =>
({
names: chunk.name ? [chunk.name] : [],
files: chunk.files.slice(),
size: chunk.modulesSize(),
hash: chunk.hash
})
);
}
);
});
}
}
```
Doesn't seem to improve much on the performance compared to using .getStats(), though, at least in the scenario I've tested.
It would be great if the autofill could be integrated in the HtmlWebpackPlugin.
I'll try to get this into html-webpack-plugin 4:
Hi @jantimon,
I am facing same situation where I think HTMLWebpakcPlugin should provide a way to allow including entry chunk + all other needed(vendors/common) chunks generated for that entry through optimization.splitChunks on its own but its just not doing it correctly.
Is it included as part of 4.0.0-alpha or it would be coming through upcoming version?
In another weird scenario:
Plugin is including chunk js multiple times If I don't define "chunks" property in config Object.
Is "chunk" property mandatory in config object for HTMLWebpakcPlugin ?
It has not been included in 4.0.0-alpha yet but I would love to merge the idea of @dmarku into the 4.x branch to fix it
Sorry for the delay - I finally managed to work on other blocking topics.
Autofilling seems to work now.
@dmarku @bemineni @Q-Man @palaniichukdmytro could you please check if the example
https://github.com/jantimon/html-webpack-plugin/pull/1035 covers your case correctly?
@ashoksudani I'll look into that
Thanks @jantimon
Is there any way you can publish these changes as an npm package?
@jantimon Example #1035 matches my use case from the look of it!
Right now, my project that needed this behavior changed its build process and doesn't generate multiple pages anymore, so I won't be able to try this out in practice and provide feedback for the time being.
Aside from that, I think it's a pretty neat feature and I'm excited that this is becoming a thing. Thanks for the work!
Fixed in [email protected]
Hi @jantimon ,
I tried using latest alpha.2 and it seems I am getting an error while invoking tap for "compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap" it says "Cannot read property 'tap' of undefined", while it was working all good with 3.2.0.
I am getting this error in [email protected] /InterpolateHtmlPlugin.js:26.
Let me know if you want me to debug anything aside.
Hi,
Its failing for other hooks as well e.g. cmpp.hooks.htmlWebpackPluginBeforeHtmlProcessing.tapAsync
compiler.hooks.compilation.tap('FaviconsWebpackPlugin', function (cmpp) {
compiler.hooks.compilation.tap('HtmlWebpackPluginHooks', function () {
if (!tapped++) {
cmpp.hooks.htmlWebpackPluginBeforeHtmlProcessing.tapAsync(
'favicons-webpack-plugin',
addFaviconsToHtml
);
}
});
});
ERROR: : Cannot read property 'tapAsync' of undefined.
@ashoksudani FaviconsWebpackPlugin and InterpolateHtmlPlugin are not compatible to the new hook structure of the alpha version:
https://github.com/jantimon/html-webpack-plugin/blob/webpack-4/README.md#events
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Yes, the
compilationobject provides all the information needed to generate the chunks. However, when returning the modifiedchunksarray I had to emulate the properties of the JSON stats in order to make it work.The variant I've successfully tried today:
```.js
class ChunksFromEntryPlugin {
apply (compiler) {
compiler.hooks.emit.tap('ChunksFromEntryPlugin', compilation => {
compilation.hooks.htmlWebpackPluginAlterChunks.tap(
'ChunksFromEntryPlugin',
(_, { plugin }) => {
// takes entry name passed via HTMLWebpackPlugin's options
const entry = plugin.options.entry;
const entrypoint = compilation.entrypoints.get(entry);
}
```
Doesn't seem to improve much on the performance compared to using
.getStats(), though, at least in the scenario I've tested.