【问题标题】:Babel not transpiling imported node_modules to ES5 - includes ES2015 syntaxBabel 没有将导入的 node_modules 转换为 ES5 - 包括 ES2015 语法
【发布时间】:2018-11-05 13:02:06
【问题描述】:

我的 babel+webpack 配置工作正常,但生成的包在 IE11 中无法运行,因为它包含 const 声明。我认为拥有es2015 预设足以解决这个问题?运行 $(npm bin)/babel test/some-es2015.js 会产生严格的 ES5.1 代码,因此 Babel 似乎可以工作,但在 IE11 中运行的实际代码是在从 node_modules 导入的模块中。

当在我的结果包中 grepping 'const ' 时,我会得到这样的某些行(eval 是由于 eval 源映射顺便说一句):

eval("\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst validator = __webpack_require__(/*! validator */ \"./node_modules/tcomb-additional-types/node_modules/validator/index.js\");\nconst t = __webpack_require__(/*! tcomb */ \"./node_modules/tcomb/index.js\");\nconst IP = t.refinement(t.String, validator.isIP);\nexports.IP = IP;\nexports.default = IP;\n//# sourceMappingURL=ip.js.map\n\n//# sourceURL=webpack:///./node_modules/tcomb-additional-types/lib/string/ip.js?");

需要注意的重要部分是const validator = 之类的东西。这不是 ES5.1 语法。我自己的代码似乎已经被转译为 ES5 就好了。我可以在/node_modules/tcomb-additional-types/lib/string/ip.js 中看到这个文件,他们使用const,所以这不是Babel 添加consts,而是包含它们的源。大多数其他软件包都是 ES5。

到目前为止,我发现大多数consts 来自material-ui 和tcomb-additional-types。

Babel .babelrc:

{
    "compact": false,
    "presets": [
        "es2015",
        "es2017"
    ],
    "plugins": [
        ["transform-runtime", {
            "polyfill": false,
            "regenerator": true
        }],
        "transform-class-properties",
        "transform-react-jsx",
        "transform-object-rest-spread"
    ]
}

Webpack 配置:

const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');

/** @returns {String} an absolute path */
function toRoot(rootRelativeDir) {
  return path.resolve(__dirname, '..', rootRelativeDir);
}

module.exports = {
  entry: ['./src/app.js', './styles/flex.less'].map(toRoot),
  output: {
    filename: 'bundle.js',
    path: toRoot('.webpack/dist')
  },
  resolve: {
    extensions: ['.js', '.jsx'],
    alias: {}
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              /* General options are read using .babelrc - only webpack loader specific here */
              cacheDirectory: toRoot('.webpack/babel_cache')
            }
          }
        ]
      }
    ]
  },
  plugins: [new CopyWebpackPlugin([toRoot('public')])]
};

【问题讨论】:

标签: javascript webpack babeljs


【解决方案1】:

我的根本问题是某些 Node 包不是使用 ES5 语法编写的,并且 Babel 转换由于某种原因没有转换它们。这是normal issue

找出为什么会发生这种情况非常容易(@Vincent 的回答很有帮助);我在配置中有exclude: /node_modules/。当然,删除它会“解决”问题,但会引入新问题,因为 exclude 的存在是有原因的,因为您不希望 Babel 处理其中的 每个 文件.

所以你想要的是:选择性过滤允许一些模块。

尝试构造一个允许 node_modules 下的包列表的正则表达式,但限制其余的包是繁琐且容易出错的。值得庆幸的是Webpack docs 描述了条件规则,其中exclude 是其中之一,可以是

  • 字符串:要匹配输入,必须以提供的字符串开头。 IE。绝对目录路径,或文件的绝对路径。
  • 正则表达式:已使用输入进行测试。
  • 一个函数:使用输入调用它,必须返回一个真实值才能匹配。
  • 条件数组:至少有一个条件必须匹配。
  • 一个对象:所有属性必须匹配。每个属性都有定义的行为。

创建这样的函数很容易!所以我没有使用exclude: /node_modules,而是将其更改为exclude: excludeCondition,其中excludeCondition 是以下函数:

function excludeCondition(path){

  const nonEs5SyntaxPackages = [
    'material-ui',
    'tcomb-additional-types'
  ]

  // DO transpile these packages
  if (nonEs5SyntaxPackages.some( pkg => path.match(pkg))) {
    return false;
  }

  // Ignore all other modules that are in node_modules
  if (path.match(toRoot("node_modules"))) { return true; }

  else return false;
}

这解决了我的问题,因为使用 ES2015 语法的软件包数量很少,因此将它们添加到白名单是可以管理的。

【讨论】:

  • 我自己也遇到过这个。但是你的toRoot() 函数在做什么呢?好像不是 babel 内置的东西?
  • toRoot() 是我自己的自定义路径转换器,它只创建从包根目录开始的路径。我在一个子文件夹中有这个配置文件,所以这让我摆脱了很多 "../../" 和 __dirname 等的连接。
【解决方案2】:

我遇到了类似的问题,我通过将 .babelrc.js 重命名为 babel.config.js 来解决它。

显然,.babelrc 的作用域比babel.config.js 小,如果您想了解更多相关信息,请查看这篇文章:

When to use babel.config.js and .babelrc

【讨论】:

    【解决方案3】:

    同样的问题也发生在我身上。一些节点模块不提供浏览器支持并且目标节点版本利用较新的 ES 语法。

    我遇到了一个可以转换节点模块代码的便捷包:

    https://www.npmjs.com/package/babel-engine-plugin

    它解决了我关于 IE11 支持的问题,希望对您有所帮助

    【讨论】:

    • 这似乎是一个不能真正解决问题的 hack,因为它所做的只是为 node_modules 启用 babel 转换,但阅读页面让我朝着正确的方向前进。当然是我的配置错误(我知道,但不是哪一行):罪魁祸首当然是exclude: /node_modules/。看来,我需要有选择地启用我需要转译的模块。
    猜你喜欢
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 2021-08-02
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多