如何使用babel-loader转译node_modules模块?

33
问题:我想为一个支持较老的浏览器(>=IE10)的网站建立捆绑文件。

使用 babel 7.x 以及 babel-loader 转译时,我的转译代码在旧版 Internet Explorer 11 上出现错误,因为似乎默认情况下 node_modules 模块不会再被转译了?

问题:如果包作者没有对已有的模块进行转译,那么我该如何确保所有node_module模块都被转译了呢?

webpack.config.js 使用 babel-loader

// webpack.config.js
rules: [
    {
        test: /\.(js|jsx)$/,
        use: [
            {
                loader: 'babel-loader',
            },
        ],
        exclude: [],
    },
],

使用Babel 7.x的babelrc.js配置

// .babelrc.js
module.exports = function(api) {
    const presets = [
        [
            '@babel/preset-env',
            {
                useBuiltIns: 'usage',
                ignoreBrowserslistConfig: true,
                targets: {
                    node: 8,
                    browsers: [
                        'last 3 versions',
                        '> 1% in DE',
                        'Explorer >= 10',
                    ],
                },
            },
        ],
        '@babel/preset-react',
    ];

    const plugins = [
        // ...
    ];

    return {
        presets,
        plugins,
    };
};

更新 1:

这是一个 babel 的问题。我的 babel 配置文件命名为 .babel.rc,而 babel 7 的默认设置是寻找名为 babel.config.js 的配置文件,请参见此处

因此,将 babel 配置文件从´.babel.rc´重命名为´babel.config.js´后,我可以在我的´webpack.config.js´中应用解决方案,如此处所述,以转换未转换的´node_modules´包的解决方案类似于以下内容:

// webpack.config.js
rules: [
    {
        test: /\.(js|jsx)$/,
        use: [
            {
                loader: 'babel-loader',
            },
        ],
        // Exclude the untransformed packages from the exclude rule here
        exclude: /node_modules\/(?!(MY_MODULE|ANOTHER-ONE)\/).*/, 
    },
],

问题:感觉这只是一种变通方法,但没有更方便的处理这些问题的方式吗?我认为在不久的将来会有越来越多未转换的包(参考此讨论),我们总是需要手动将包名称放入 webpack 的exclude规则中吗?


1
你可以确保不向 exclude: [] 选项中添加任何内容。 - PlayMa256
@PlayMa256:你是指在 webpack.config.js 中吗?我已经尝试过了,但没有任何变化。同样,在 .babelrc.js 配置中添加 exclude: [] 也没有变化。 - Michael
请查看此链接 https://github.com/webpack/webpack/issues/2031 - AKT
好的,这是一个有关于 babel 的问题。我的 babel 配置文件被命名为 .babel.rc,但是在某个时候,babel 更改了查找 babel 配置文件的默认设置为 babel.config.js,请参考此处链接:https://babeljs.io/docs/en/options#configfile。因此,在重命名配置文件后,exclude: /node_modules\/(?!(MY_MODULE |ANOTHER-ONE)\/).*/, 解决方案现在可以正常工作了。 - Michael
谢谢!!! 特别是这个页面帮了我大忙 https://babeljs.io/docs/en/config-files#6x-vs-7x-babelrc-loading - Eric
2个回答

5
问题:感觉这只是一个变通办法,是否有更方便的方法来处理这样的问题?我假装在不久的将来会有越来越多未转换的包(遵循这个讨论),难道我们总是要手动将这些包的名称放入webpack的排除规则中吗?
您可以使用像“are-you-es5”这样的模块自动创建异常列表或测试:https://www.npmjs.com/package/are-you-es5 另外,像“eslint-plugin-compat”这样的工具也可以在指向您的node_modules时警告您存在的问题:https://www.npmjs.com/package/eslint-plugin-compat 但它并非完美。我认为在生产环境设置中,您应该仅在添加之前注意添加的软件包或者进行一些自动化测试,以捕获浏览器错误,如果IE11对于您的项目至关重要。
我知道这并不总是可能的,但我强烈建议将IE11及以下推至较低层级支持。在使用现代JS的同时仍然维护IE11及以下版本非常困难。

0
我知道这是一个老问题,但最近我花了很多时间来解决同样的问题,所以我也想分享一下我的经验。
首先,exclude: /node_modules\/(?!(MY_MODULE|ANOTHER-ONE)\/).*/ 只适用于*nix系统,而不适用于Windows系统,因为Windows使用/作为路径分隔符,所以一个通用的解决方案是使用正则表达式exclude: /node_modules(?!(\/|\\)MY_MODULE|ANOTHER-ONE)/ 其次,使用负向先行断言的正则表达式确实感觉有些奇怪,而https://github.com/babel/babel-loader#some-files-in-my-node_modules-are-not-transpiled-for-ie-11有一个更好的方法。
exclude: {
      and: [/node_modules/], // Exclude libraries in node_modules ...
      not: [
        // Except for a few of them that needs to be transpiled for IE
        /unfetch/,
        /d3-array|d3-scale/,
        /@hapi[\\/]joi-date/,
      ]
    },

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接