为什么在使用`useBuiltIns: "usage"`的情况下,使用babel preset-env会导致在harmony-module中出现错误?

3
我正在尝试配置babel preset-env,以自动注入polyfills,与指定的目标浏览器列表相关。文档说明,使用形式为"useBuiltIns":"usage"的属性配置preset-env预设将完全做到这一点。(我注意到仅指定此属性会在控制台中显示警告,建议我应该指定要使用的core-js版本,因此我也添加了它。)因此,我的babel.config.js看起来像这样:
module.exports = {
  "presets": [
    "@babel/preset-react",
    "@babel/preset-typescript",
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ],
  "plugins": ['macros'],
};

太棒了!这应该很容易!

然而,使用webpack重新编译后,我的应用现在在浏览器中崩溃了,并显示控制台消息:

Uncaught TypeError: __webpack_require__(...) is not a function
at Module../node_modules/webpack/buildin/harmony-module.js (harmony-module.js:24)

我已经做了一些研究(只有大约3个小时!),我理解这是babel试图转译babel的结果,或者类似的情况...我需要将一些文件添加到忽略列表中,这些文件不会被转译,或者说不会被双重转译。

在我的webpack配置中,我添加了以下内容。(请注意排除条目)。

module: {
  rules: [
    {
      test: /\.(js|jsx|ts|tsx)$/,
      exclude: [/core-js/, /regenerator-runtime/],
      use: [
        {
          loader: 'babel-loader',
          options: {
            presets: babelConfig.presets,
            cacheDirectory: babelCacheDir
          }
        },
        'eslint-loader'
      ]
    }
  ]
}

我还尝试了在忽略模式中添加一些变化,但我仍然遇到致命的控制台错误。
另一件我尝试过的事情是忽略node_modules文件夹,但是那样我就有了大块未进行转码的代码。例如,在IE11中,我会得到有关ES6箭头函数的语法错误,这些错误源于未进行转码的供应商脚本。
如果有人能够解释为什么__webpack_require__以一种不希望的方式被更改,我将非常感激,因为这个问题需要确切的解决方案,很难找到。
编辑:以下内容建议让babel忽略core-js,这似乎非常合理。它建议在babel配置文件中使用以下内容:
{
  ignore: [
    /\/core-js/,
  ],
  sourceType: "unambiguous",
  presets: [
    ['@babel/preset-env', { modules: false, useBuiltIns: 'usage' }],
  ],
}

然而,这会引起另一个相当的、看似不具体的错误出现:
has.js:4 Uncaught TypeError: Cannot convert undefined or null to object
    at hasOwnProperty (<anonymous>)
    at push../node_modules/core-js/internals/has.js.module.exports (has.js:4)

很好的问题。似乎将 useBuiltIns: 'usage' 设置带来了比以前更多的 Babel 管道,以前可以正常工作的事情(在我的情况下,导入使用赋值到 module.exports 的 node.js 风格代码)现在会出现问题。使用 sourceType: "unambiguous" 对我有所帮助,但可能因人而异。(https://dev59.com/i1QK5IYBdhLWcg3wHsdJ#52415747) - DomQ
2个回答

2
useBuiltins: "usage" 下,Babel 需要猜测 ES6 和 CJS 导入样式,并且最好与 Webpack 猜测方式相同。这在Babel文档中简要介绍了。如其他地方所解释的那样,使其发生的最简单方法是在传递给 @babel/preset-env 的选项中还设置sourceType: "不明确"。使用 useBuiltIns: "usage" 意味着 Babel 将寻找并填充一些浏览器中可能不存在的方法调用(和其他 JS 构造)的 polyfill。这需要在 Babel 重写时向模块注入一些修复代码。其中许多修复程序包括导入 core-js 的部分,以确保 Array 等原型得到满足;例如,Babel 可能会插入诸如
import "core-js/modules/es.array.map.js";
的内容。不幸的是,在 JavaScript 中有多种导入方式。Babel 必须猜测哪种对下游工具链最好。如果 Babel 在 Webpack 上游,这是一个非常典型的情况(也是您的问题的情况),它可能通过向使用 require()module.exports 的代码添加 import 语句而破坏 Webpack 中的一些自动检测逻辑。Webpack 会不幸地尝试处理这种被污染的代码;导致各种晦涩难懂的编译时或运行时症状(这里是另一个例子)。在 Babel 和 Webpack 就某种惯例或秘密握手达成一致之前,作为模块作者,您必须确保 Babel 和 Webpack 对使用哪种格式的源文件具有相同的想法;或者只禁用您的“旧”(CJS)代码的 Babel,无论是在 node_modules/ 还是其他地方。

0

对我来说,排除/webpack/就解决了问题!


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