Customizable options for `HtmlWebpackPlugin`
- Dominant language
- TypeScript
- Stars
- 7.1k
- Forks
- 641
- Avg merge
- 3d 1h
- Merged PRs (30d)
- 30
Description
### Pre-flight checklist
- [X] I have read the [contribution documentation](https://github.com/electron-userland/electron-forge/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [code of conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project uses.
- [X] I have searched the issue tracker for a feature request that matches the one I want to file, without success.
### Problem description
I want to adjust the output from `HtmlWebpackPlugin`, or use addons with it via the `@electron-forge` Webpack plugin. But, because `@electron-forge/plugin-webpack` uses the `HtmlWebpackPlugin` privately, and no such options are provided, the plugin invocation cannot be adjusted.
As a user, I still want to leverage `@electron-forge`'s built-in configuration of `HtmlWebpackPlugin`, just with adjusted parameters and extra add-ons.
Additionally, some plugins need to be invoked _only when the HTML plugin is invoked_, which leaves no opportunity in the existing Forge configuration structure to safely declare the plugin.
### Proposed solution
I would like to propose three new properties to be added to `WebpackConfig.ts`:
**`Config.ts`:**
```typescript
export interface WebpackPluginEntryPoint {
//...
/**
* Custom options to merge into the configuration passed to `HtmlWebpackPlugin`.
*/
htmlOptions?: Partial;
/**
* Plugins to include before `HtmlWebpackPlugin`; typically, HTML plugin add-ons will
* need to be placed here.
*/
htmlPlugins?: WebpackPlugin[];
/**
* Additional options to merge into the Webpack `output` configuration for this entry-
* point.
*/
output?: object;
}
```
These options would be passed to the `HtmlWebpackPlugin` invocation via `Object.assign(...)`, like so:
**`Config.ts`:**
```diff
@@ -161,28 +161,29 @@ class WebpackConfigGenerator {
target: this.rendererTarget(entryPoint),
devtool: this.rendererSourceMapOption,
mode: this.mode,
- output: {
+ output: Object.assign(entryPoint.output || {}, {
path: _path.default.resolve(this.webpackDir, 'renderer'),
filename: '[name]/index.js',
globalObject: 'self',
...this.isProd ? {} : {
publicPath: '/'
}
- },
+ }),
node: {
__dirname: false,
__filename: false
},
plugins: [
+ ...(entryPoint.htmlPlugins || []),
...entryPoint.html ? [
- new _htmlWebpackPlugin.default({
+ new _htmlWebpackPlugin.default(Object.assign({}, {
title: entryPoint.name,
template: entryPoint.html,
filename: `${entryPoint.name}/index.html`,
chunks: [
entryPoint.name
].concat(entryPoint.additionalChunks || [])
- }),
+ }, entryPoint.htmlOptions || {}))
] : [],
new _webpack.default.DefinePlugin(defines),
new _assetRelocatorPatch.default(this.isProd, !!this.pluginConfig.renderer.nodeIntegration),
```
Then, in `forge.config.js`, the user can control these parameters:
**`forge.config.js`**:
```js
"plugins": [
[
"@electron-forge/plugin-webpack",
{
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.tsx",
"name": "main_window",
"preload": {"js": "./src/preload.ts"},
// 👇 control over output options needed for some plugins
"output": {
"crossOriginLoading": "anonymous",
},
// 👇 custom HTML plugin options
"htmlOptions": {
"minify": true
},
// 👇 add-ons for HtmlWebpackPlugin here
"htmlPlugins": [
new SubresourceIntegrityPlugin(),
]
}
]
}
}
],
```
### Alternatives considered
I have considered:
**1) Suppressing HTML features in `@electron-forge/plugin-webpack`.**
This is sub-optimal because the plugin still drives chunking, entrypoints, etc., and is very useful in this regard. I don't want to have to make a trade-off decision between these benefits and custom options.
**2) Mounting as regular plugins.**
When I try to use HTML plugin add-ons as regular plug-ins, they end up in the plugin list _after_ `HtmlWebpackPlugin`, and so their output isn't picked up.
**3) Patching.**
We're doing this currently via Yarn and it's working great, but this limits the benefits only to us and forces maintenance of the patch. The plugin's approach is solid, it just needs extra options to allow users to get in there and customize the invocation.
### Additional information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.