【问题标题】:Why does using babel preset-env with `useBuiltIns: "usage"` cause an error in harmony-module?为什么将 babel preset-env 与 `useBuiltIns: "usage"` 一起使用会导致 Harmony 模块出错?
【发布时间】:2020-05-31 06:32:33
【问题描述】:

我正在尝试配置 babel preset-env 以处理针对指定目标浏览器列表的自动注入 polyfill。

文档指出,使用"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__ 会以一种不受欢迎的方式被更改,我会非常感激,因为这个问题需要的确切解决方案是相当难以研究。

编辑:following 建议 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" 帮助了我,YMMV。 (stackoverflow.com/a/52415747/435004)

标签: webpack babeljs babel-preset-env


【解决方案1】:

useBuiltins: "usage" 下,Babel 需要猜测一下。 ES6 与 CJS 导入样式;并且最好和 Webpack 一样猜测。

the Babel docs 对此进行了简要介绍。正如elsewhere 所解释的那样,实现这一目标的最简单方法是在传递给@babel/preset-env 的选项中也设置sourceType: "unambiguous"

尽我所能回答“为什么”的问题:

  • useBuiltIns: "usage" 意味着 Babel 将着手查找和 polyfill 一些可能在某些浏览器中不存在的方法调用(和其他 JS 构造)。这需要在 Babel 重写时将一些修复代码注入到您的模块中。
  • 其中很多修正包括导入core-js 的片段,以确保阵列等原型的填充满意;例如Babel 可以插入诸如
    import "core-js/modules/es.array.map.js";
    之类的东西
  • 很不幸,JavaScript 中有more than one way to import things。 Babel 必须猜测哪个最适合下游工具链。如果 Babel 位于 Webpack 的上游,这是一个非常典型的场景(您的问题就是这种情况),它可能会通过在使用 require()module.exports 的代码中添加 import 语句来破坏一些 auto-detection logic in Webpack。李>
  • 不幸的是,Webpack 不会直接抛出解析错误,而是尝试处理这些受污染的代码;导致各种难以理解的编译时或运行时症状 (here is another example)。

直到 Babel 和 Webpack 同意某种约定或秘密握手以解决 ES6 / CJS 阻抗不匹配问题,作为模块作者,您必须以某种方式确保 Babel 和 Webpack 有相同的想法源文件使用哪种格式;或者只是为您的“旧”(CJS)代码禁用 Babel,无论是在 node_modules/ 还是其他地方。

【讨论】:

    【解决方案2】:

    排除 /webpack/ 对我有用!

    【讨论】:

      猜你喜欢
      • 2020-05-06
      • 1970-01-01
      • 2021-03-03
      • 2016-02-04
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-13
      相关资源
      最近更新 更多