-
Notifications
You must be signed in to change notification settings - Fork 233
Unhelpful error message when adding minimizer ("TypeError: Cannot read property '__expression' of undefined") #204
Comments
Hi! Thank you for filing an issue. I'm not able to reproduce using: // package.json
{
"dependencies": {
"terser-webpack-plugin": "2.1.3",
"webpack": "4.41.1",
"webpack-chain": "6.0.0"
}
} // test.js
const Config = require('webpack-chain');
const config = new Config();
const TerserPlugin = require('terser-webpack-plugin');
config.optimization
.minimizer('terser')
.use(TerserPlugin);
console.log(config.toConfig());
console.log(config.toString()); $ node --version
v12.11.1
$ node test.js
{ optimization: { minimizer: [ [TerserPlugin] ] } }
{
optimization: {
minimizer: [
/* config.optimization.minimizer('terser') */
new TerserPlugin()
]
}
} Could you create a reduced testcase that shows the error? |
I had same issue (with TerserPlugin). My problem was that I used vue-cli-plugin-nativescript-vue with vue-cli 4.x |
The same problem has arisen // Please ignore the above references
import Config from "webpack-chain";
import common from "./webpack.common";
import TerserPlugin from "terser-webpack-plugin";
const config = new Config();
config.mode("production");
config.optimization.minimizer("terser").use(TerserPlugin);
export default common.merge(config.toConfig()).toConfig(); package.json{
"webpack": "^4.41.3",
"terser-webpack-plugin": "^2.3.0",
"webpack-chain": "^6.2.0",
} error const constructorName = plugin.__expression
^
TypeError: Cannot read property '__expression' of undefined |
@bosens-China Hi! Please can you create a fully contained testcase that demonstrates the issue? And file as a new issue? I can't use the above, since |
me too |
Thank you for this clue. Checking out that vue plugin, I can see it's still using the old webpack-chain <= 4 syntax for The solution is either to downgrade to webpack chain 4 (by downgrading Vue CLI to v3) or else fork that plugin and update it to be compatible with webpack 5+ that comes with newer Vue CLI. This seems like a common enough problem that it would be worth adding some additional error checking to webpack-chain so we can display a more user-friendly error message (even though this is not a webpack-chain bug itself). |
The data structure that is passed to `.merge()` is very similar to a webpack configuration object, but has a few key differences. The current docs don't make this clear enough, such that some users have been trying to pass the output of `.toConfig()` back to `.merge()`, which can cause errors: #204 (comment)
In #84 (released as part of webpack-chain 5.0.0) the syntax for using `optimization.minimizer` was altered, so that it matched that for `plugin`, `resolve.plugin` and `resolveLoader.plugin`. Syntax in webpack-chain 4: ``` config.optimization.minimizer([ new WebpackPluginFoo(), new WebpackPluginBar(arg1, arg2), ]); ``` Syntax in webpack-chain 5+: ``` config.optimization.minimizer('foo').use(WebpackPluginFoo); config.optimization.minimizer('bar').use(WebpackPluginBar, [arg1, arg2]); ``` Currently if someone uses the old syntax with newer webpack-chain, then the `minimizer()` call succeeds, but later when `.toConfig()` is called, the following error is generated: `TypeError: Cannot read property '__expression' of undefined` This PR adds an explicit check to `optimization.minimizer()` which ensures a clearer error message is shown at point of use, so that the stack trace is more relevant, and root cause clearer. Refs: #204 (comment)
I've dug into this more yesterday/today. This error message is shown when the plugin configuration is incomplete, which can happen in a variety of ways. Whilst this isn't a webpack-chain bug, showing unhelpful error messages is not ideal and we should add additional error checking at other locations, to make it easier to work out what is invalid about the configuration, so that users can fix it themselves. Scenario 1In its simplest form, this error message can be triggered like so: const webpackChain = require('webpack-chain');
const config = new webpackChain();
config.plugin('name');
// We forgot to call .use() before .toConfig()!
// config.plugin('name').use(SomePlugin);
config.toConfig();
The nature of webpack-chain's API for adding plugins, means it's a multi-part process, and if the To handle this case, we could add a check inside Plugin's Scenario 2:Using the legacy config.optimization.minimizer([
new WebpackPluginFoo(),
new WebpackPluginBar(arg1, arg2),
]); ...rather than the new syntax from webpack-chain 5+: config.optimization.minimizer('foo').use(WebpackPluginFoo);
config.optimization.minimizer('bar').use(WebpackPluginBar, [arg1, arg2]); This can happen when eg using Vue CLI 4 with a Vue plugin that's not yet been made compatible with it. This case we can handle more specifically, by checking whether an array was passed to Scenario 3:Trying to pass a webpack-chain style configuration object into eg: const webpackChain = require('webpack-chain');
const config1 = new webpackChain();
const config2 = new webpackChain();
class TestPlugin {}
config2.optimization.minimizer("terser").use(TestPlugin);
// This is not valid usage of `.merge()` and isn't expected to work!
config1.merge(config2.toConfig()).toConfig(); There are a few issues here:
Personally I'm not a big fan of |
In #84 (released as part of webpack-chain 5.0.0) the syntax for using `optimization.minimizer` was altered, so that it matched that for `plugin`, `resolve.plugin` and `resolveLoader.plugin`. Syntax in webpack-chain 4: ``` config.optimization.minimizer([ new WebpackPluginFoo(), new WebpackPluginBar(arg1, arg2), ]); ``` Syntax in webpack-chain 5+: ``` config.optimization.minimizer('foo').use(WebpackPluginFoo); config.optimization.minimizer('bar').use(WebpackPluginBar, [arg1, arg2]); ``` Currently if someone uses the old syntax with newer webpack-chain, then the `minimizer()` call succeeds, but later when `.toConfig()` is called, the following error is generated: `TypeError: Cannot read property '__expression' of undefined` This PR adds an explicit check to `optimization.minimizer()` which ensures a clearer error message is shown at point of use, so that the stack trace is more relevant, and root cause clearer. Refs: #204 (comment)
) The data structure that is passed to `.merge()` is very similar to a webpack configuration object, but has a few key differences. The current docs don't make this clear enough, such that some users have been trying to pass the output of `.toConfig()` back to `.merge()`, which can cause errors: #204 (comment)
v6.3.1 has just been released, which includes some improvements to the error message shown in some of the scenarios outlined above, which should make it easier to self-debug what's broken in project's usage of webpack-chain. I still want to improve the error message for scenario 1 and scenario 3.3, so leaving this open for now :-) |
Previously if `.toConfig()` was called when a plugin was only partially configured, it raised with the unhelpful: `TypeError: Cannot read property '__expression' of undefined` Now the scenario results in an Error of form: `Invalid plugin configuration: plugin('foo').use(<Plugin>) was not called to specify the plugin` Or for minimizer plugins: `Invalid optimization.minimizer configuration: optimization.minimizer('foo').use(<Plugin>) was not called to specify the plugin` Fixes scenario 1 in: #204 (comment)
Previously if `.toConfig()` was called when a plugin was only partially configured, it raised with the unhelpful: `TypeError: Cannot read property '__expression' of undefined` Now the scenario results in an Error of form: `Invalid plugin configuration: plugin('foo').use(<Plugin>) was not called to specify the plugin` Or for minimizer plugins: `Invalid optimization.minimizer configuration: optimization.minimizer('foo').use(<Plugin>) was not called to specify the plugin` Fixes scenario 1 in: #204 (comment)
Previously if `.toConfig()` was called when a plugin was only partially configured, it raised with the unhelpful: `TypeError: Cannot read property '__expression' of undefined` Now the scenario results in an Error of form: `Invalid plugin configuration: plugin('foo').use(<Plugin>) was not called to specify the plugin` Or for minimizer plugins: `Invalid optimization.minimizer configuration: optimization.minimizer('foo').use(<Plugin>) was not called to specify the plugin` Fixes scenario 1 in: #204 (comment)
i tried, it working when NODE_ENV === 'production' but when NODE_ENV !== 'production' chainWebpack: config => {
config.optimization
.minimizer('terser')
.tap(args => {
if (process.env.NODE_ENV === 'production') {
args[0].terserOptions.compress.drop_console = true
args[0].terserOptions.compress.drop_debugger = true
}
return args
})
} |
I want to explicitly add (in order to configure) the Terser Plugin as minimizer to a webpack config with
webpack-chain
v6.0.0.The code
results in the error
Any idea what the problem might be?
The text was updated successfully, but these errors were encountered: