html-webpack-plugin: compilation.getAssetPath is not a function when using yarn workspaces
Expected behaviour
The way webpack version is resolved to determine which api to use in L162 and L540 delegates to nodejs the wepack resolution, this causes version mismatch in cases where the dependencies are hoisted. It should resolve the webpack.config.js where was required to determine the api version.
Current behaviour
This error is produced because @storybook/react uses a wepack@4.44.2 version, and html-webpack-plugin is picking the root webpack@5.3.2 instead of the local one.
(node:50947) UnhandledPromiseRejectionWarning: TypeError: compilation.getAssetPath is not a function
at compiler.hooks.emit.tapAsync (.../cnix-ui/node_modules/html-webpack-plugin/index.js:164:25)
at AsyncSeriesHook.eval [as callAsync] (eval at create (.../cnix-ui/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:27:1)
at AsyncSeriesHook.lazyCompileHook (.../cnix-ui/node_modules/tapable/lib/Hook.js:154:20)
at Compiler.emitAssets (.../cnix-ui/node_modules/@storybook/core/node_modules/webpack/lib/Compiler.js:491:19)
at onCompiled (.../cnix-ui/node_modules/@storybook/core/node_modules/webpack/lib/Watching.js:51:19)
at hooks.afterCompile.callAsync.err (.../cnix-ui/node_modules/@storybook/core/node_modules/webpack/lib/Compiler.js:681:15)
at AsyncSeriesHook.eval [as callAsync] (eval at create (.../cnix-ui/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
at AsyncSeriesHook.lazyCompileHook (.../cnix-ui/node_modules/tapable/lib/Hook.js:154:20)
at compilation.seal.err (.../cnix-ui/node_modules/@storybook/core/node_modules/webpack/lib/Compiler.js:678:31)
at AsyncSeriesHook.eval [as callAsync] (eval at create (.../cnix-ui/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
at AsyncSeriesHook.lazyCompileHook (.../cnix-ui/node_modules/tapable/lib/Hook.js:154:20)
at hooks.optimizeAssets.callAsync.err (.../cnix-ui/node_modules/@storybook/core/node_modules/webpack/lib/Compilation.js:1423:35)
at AsyncSeriesHook.eval [as callAsync] (eval at create (.../cnix-ui/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
at AsyncSeriesHook.lazyCompileHook (.../cnix-ui/node_modules/tapable/lib/Hook.js:154:20)
at hooks.optimizeChunkAssets.callAsync.err (.../cnix-ui/node_modules/@storybook/core/node_modules/webpack/lib/Compilation.js:1414:32)
at AsyncSeriesHook.eval [as callAsync] (eval at create (.../cnix-ui/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
(node:50947) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 8)
Environment
darwin 19.6.0
npm 6.13.4
yarn list webpack
warning Filtering by arguments is deprecated. Please use the pattern option instead.
├─ @storybook/addon-docs@6.0.28
│ └─ webpack@4.44.2
├─ @storybook/react@6.0.28
│ └─ webpack@4.44.2
└─ webpack@5.3.2
✨ Done in 1.45s.
yarn list html-webpack-plugin
warning Filtering by arguments is deprecated. Please use the pattern option instead.
└─ html-webpack-plugin@4.5.0
✨ Done in 1.10s.
Posible Solution
It would be more simple if instead of use the version matching use a fallback call providing the newest api definition firts, ie:
--- html-wepack-plugin.cur 2020-11-01 12:19:09.450509028 +0100
+++ node_modules/html-webpack-plugin/index.js 2020-11-01 12:19:16.304563095 +0100
@@ -161,9 +161,8 @@
hash: templateResult.mainCompilationHash
};
- const childCompilationOutputName = webpackMajorVersion === 4
- ? compilation.mainTemplate.getAssetPath(this.options.filename, compiledEntries)
- : compilation.getAssetPath(this.options.filename, compiledEntries);
+ const getAssetPath = (compilation.getAssetPath || compilation.mainTemplate.getAssetPath).bind(compilation);
+ const childCompilationOutputName = getAssetPath(this.options.filename, compiledEntries);
// If the child compilation was not executed during a previous main compile run
// it is a cached result
or even better if there is a global call polyfill like this:
const getAssetPath = (compilation, ...args) => compilation.getAssetPath ? compilation.getAssetPath(...args) : compilation.mainTemplate.getAssetPath(...args);
Another solution to keep the logic untouched would be resolve webpack version taking in mind which component is requiring this module, ie @storybook/react is requiring in its webpack config so resolving the webpack from the parent module will obtain the version used in webpack.config.js, but this is potentially dangerous and deprecated. so in favor of simplify the logic the polyfill solution would be the best choice.
Relevant Links
PR https://github.com/jantimon/html-webpack-plugin/pull/1547
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 4
- Comments: 15 (3 by maintainers)
use yarn add html-webpack-plugin@next -D, this resolve
Thanks for the help above. I ran into this in my Storybook build job as well today.
Errors:
Resolved it by manually adding this dependency:
Feels like a bandaid, but it works for now.
is there a solution here that doesn’t require installing an unnecessary dependency? with server-side rendering, i’m not using html-webpack-plugin
check this project that I structured with webpack and storybook https://github.com/deeborges/archetype-react
@Robbie-Cook yes I am trying to release it as
@latestsoon.