将白名单选项与 Babel 的外部助手一起使用

Using the whitelist option with Babel's external-helpers

我正在尝试将 Rollup 与 Babel 的 external-helpers 一起使用。它有效,但它丢弃了一堆我什至不需要的 babel 助手,例如 asyncGenerator。

文档 show a whitelist option 但我无法让它工作

rollup.rollup({
    entry: 'src/buttonDropdown.es6',
    plugins: [
        babel({
            presets: ['react', ['es2015', { modules: false }], 'stage-2'],
            plugins: [['external-helpers', { whitelist: ['asyncGenerator'] }]]
        })
    ]
})

以上没有任何效果:所有 Babel 助手仍然放入我生成的包中。

使用此功能的正确方法是什么?是否有白名单数组采用的助手名称的完整列表?

或者是否有其他一些 Rollup 插件我应该与 Rollup 一起使用以自动 "tree shake" babel 外部助手。

正如我在 GitHub 页面的这个特定 issue 中所发现的那样。

Babel 成员Hzoo 建议

Right now the intention of the preset is to allow people to use it without customization - if you want to modify it then you'll have to just define plugins yourself or make your own preset.

但是,如果您想从默认预设中排除特定插件,那么这里有一些步骤。 正如 Krucher 所建议的,您可以通过以下方式为不需要的插件创建一个分支

  • 第一个是通过分叉技术

    "babel": {
    "presets": [
      "es2015"
    ],
    "disablePlugins": [
        "babel-plugin-transform-es2015-modules-commonjs"
    ]
    

    }

但是如果两个或更多人想要包含 es2015-with-commonjs 那么它会是一个 problem.For 你必须 define your own presetextend 该模块的预设.

  • 第二种方法涉及tree-shaking as shown in this article done by Dr. Axel Rauschmayer。 根据文章 webpack2Babel6 一起使用。 这有助于以两种方式删除可能在项目中的任何地方使用的不需要的导入

    1. 首先,将所有ES6模块文件组合成一个single bundle file。在该文件中,未在任何地方导入的导出不再导出。
    2. 其次,捆绑为minified,同时消去dead code。因此,既未导出也未在其模块内使用的实体不会出现在缩小包中。如果没有第一步,死代码消除将永远不会删除导出(注册导出使其保持活动状态)。

其他细节可以在文章中找到。

简单的实现被称为here

  • 第三种方法涉及为特定模块创建自己的预设。

创建插件和修改自己的预设可以根据文档实现here

此外,作为额外提示,您还应该使用 babel-plugin-transforn-runtime 如果您的任何模块具有外部依赖性,则 bundle 作为一个整体将具有相同的 external dependancy,无论您是否实际使用它可能具有一些 side-effects.

rollup.js 的 tree shaking 也有很多问题 article

Also as shown in the presets documentation

默认启用

这些插件不再有效,因为较新的 babylon 版本默认启用它们

- async-functions (since babylon 6.9.1)
- exponentiation-operator (since babylon 6.9.1)
- trailing-function-commas (since babylon 6.9.1)**

此外,loganfsmyth here in this 对插件的白名单和黑名单的概念进行了精彩的解释。

you can pass a whitelist option to specify specific transformations to run, or a blacklist to specific transformations to disable.

You cannot blacklist specific plugins, but you may list only the plugins you want, excluding the ones you do not wish to run.

更新:

根据这个 article 这里有一个重要的更新 -

"The --external-helpers option is now a plugin. To avoid repeated inclusion of Babel’s helper functions, you’ll now need to install and apply the babel-plugin-transform-runtime package, and then require the babel-runtime package within your code (yes, even if you’re using the polyfill)."

希望这可以解决您的问题

希望对您有所帮助。

问题

babel-plugin-external-helpers 插件不负责在最终包中注入这些依赖项。 它唯一控制的是生成的代码将如何访问这些函数。例如:

classCallCheck(this, Foo);
// or
babelHelpers.classCallCheck(this, Foo);

它是必需的,所以 rollup-plugin-babel 需要做的就是在每个模块中注入 babelHelpers

文档具有误导性,whitelist 选项不在 external-helpers 插件 上。它在 completely separate module and command line tool called babel-external-helpers 上,它实际上负责生成 babelHelpers.

它是 rollup-plugin-babel 正在注入 babelHelpers. 并且使用技巧来模块化最终代码。它调用 babel-external-helpers 来生成助手,and ignores the whitelist parameter. See my issue requesting to expose an option.

这种方法是正确的,因为 rollup 会对未使用的辅助函数进行 tree-shaking。然而,一些帮助程序(如 asyncGenerator)的编写方式很难检测到初始化是否有任何副作用,从而防止在 tree-shaking 期间被删除。

解决方法

forked rollup-plugin-babel 并创建了一个 PR,它公开了在插件选项中构建 babelHelpers 的白名单选项。可以这样使用:

require("rollup").rollup({
  entry: "./src/main.js",
  plugins: [
    require("rollup-plugin-babel")({
      "presets": [["es2015", { "modules": false }]],
      "plugins": ["external-helpers"],
      "externalHelpersWhitelist": ['classCallCheck', 'inherits', 'possibleConstructorReturn']
    })
  ]
}).then(bundle => {
  var result = bundle.generate({
    format: 'iife'
  });
  require("fs").writeFileSync("./dist/bundle.js", result.code);
}).then(null, err => console.error(err));

请注意,我没有在 npm 上发布分发版本,您必须克隆 git 存储库并使用 rollup -c.[ 构建它=28=]

解决方案

在我看来,正确的解决方案是以某种方式检测或告诉 rollup 这些导出是纯净的,因此可以通过 tree shaking 删除。做一些研究后,我将在 github 上开始讨论它。