为什么我的 Mutex class 没有被 Webpack 转译?

Why isn't my Mutex class being transpiled by Webpack?

我在从 Webpack 4 升级到 Webpack 5 时遇到问题,Babel 似乎不再从我的依赖项之一转换代码 (async-mutex)。我设法将其简化为可证明问题的最小设置:

package.json

{
    "scripts": {
        "build": "webpack --mode=production"
    },
    "devDependencies": {
        "@babel/core": "~7.12.0",
        "@babel/preset-env": "~7.12.0",
        "async-mutex": "~0.2.0",
        "babel-loader": "~8.2.0",
        "webpack": "~5.10.0",
        "webpack-cli": "~4.2.0"
    },
    "babel": {
        "presets": [
            "@babel/preset-env"
        ]
    },
    "browserslist": [
        "Explorer >= 11"
    ]
}

webpack.config.js

module.exports = {
    entry:  {
        bundle: './index.js',
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                use:  'babel-loader',
            },
        ],
    },
};

index.js

import {Mutex} from 'async-mutex';
console.log(Mutex);

class MyClass {}
console.log(MyClass);

根据我的浏览器列表,我需要支持 IE 11。在构建它并检查生成的 dist/bundle.js 之后,我可以看到 class MyClass 被转换成一个函数,但是 class Mutex 没有被转译,这显然会导致 IE 11 因语法错误而失败。就好像 Babel 使用不同的设置来处理 async-mutex 包而不是用来处理我的 index.js.

我发现 建议添加 target: ['web', 'es5'],但这没有用,而且似乎也没有必要,因为 Webpack 应该支持浏览器列表。

使用 Webpack 4 我没有遇到这个问题,但我不确定问题是否出在我的设置、Webpack、Babel 甚至 async-mutex 上。

注意:我知道这个最小设置缺少 Promise polyfill,但我在这里省略它,因为它似乎与问题无关。

您需要在 webpack.config.js 的 babel 模块规则中包含 async-mutex。偶尔你会遇到一个没有转换它的 ES6 的包。有趣的是,将它包含在你的转译中的最好方法是使用 exclude,像这样:


module.exports = {
    entry:  {
        bundle: './index.js',
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules\/(?!(async-mutex)\/).*/,
                use:  'babel-loader',
            },
        ],
    },
};

这条排除规则说,“排除所有 node_modulesasync-mutex”。

package.json 中的 Babel 配置仅适用于您的特定包,而不适用于 node_modules,因此即使 Babel 设置为处理您的包中的所有文件,它也仅被配置为执行转换你自己的包的文件。见 Babel config file docs.

你需要创建一个babel.config.json,或者你需要将配置直接放入Webpack配置中,所以或者

babel.config.json:

{
    "presets": [
        "@babel/preset-env"
    ]
}

webpack.config.js:

module.exports = {
    entry:  {
        bundle: './index.js',
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                use:  'babel-loader',
                options: {
                    "presets": [
                        "@babel/preset-env"
                    ]
                }
            },
        ],
    },
};