Babel不会将导入的node_modules转换为ES5-包括ES2015语法

时间:2018-11-05 13:02:07

标签: javascript webpack babeljs

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

在我的结果包中为'const '进行grepping时,我得到如下几行(评估是由于评估源映射btw):

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添加const,而是包含它们的源。其他大多数软件包都是ES5。

到目前为止,我发现大多数const来自material-uitcomb-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')])]
};

3 个答案:

答案 0 :(得分:1)

我的基本问题是某些Node软件包未使用ES5语法编写,并且Babel转换由于某种原因未对它们进行转换。这是normal issue

找到原因的事情很容易(@Vincent的回答有所帮助);我在配置中有exclude: /node_modules/。当然,删除此选项将“解决”该问题,但是它将引入新的问题,因为exclude存在是有原因的,因为您不希望Babel处理每个文件在那里。

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

试图构造一个正则表达式,该表达式将允许在node_modules下列出软件包,但限制其余的代码既麻烦又容易出错。幸运的是Webpack docs描述了条件规则,其中exclude是一个条件规则

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

创建这样的功能很容易!因此,我没有使用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语法的软件包,因此将它们添加到白名单是可管理的。

答案 1 :(得分:1)

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

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

When to use babel.config.js and .babelrc

答案 2 :(得分:0)

我也遇到了同样的问题。某些节点模块不提供浏览器支持,而目标节点版本则使用较新的ES语法。

我遇到了一个方便的软件包,该软件包可以转换节点模块代码:

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

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