分类
js

正确使用 @babel/preset-env 与 @babel/plugin-transform-runtime

这几天又在折腾项目脚手架,看到之前的配置里用到 transform-runtime,于是就想研究下。找了半天,发现现有的文章、讨论都没有准确、合理的说明,所以写篇博客介绍一下。

定位

@babel/preset-env

@babel/preset-env 是一大堆插件的集合,包含了当前浏览器环境下,所有语言特性的插件,可以根据 browserslist 的结果,选择合适的插件将新语言特性转译成旧浏览器可以支持的表达方式。

官方推荐使用预制件(preset),可以大大节省配置时间,提高开发效率。

@babel/plugin-transform-runtime

babel 转译时,往往需要用到一些工具函数,比如 _extend。转译以文件为单位,意味着每个文件里都可能有重复的 babel 工具函数。现代化项目常有大量的文件,就可能产生重复和浪费。

@babel/plugin-transform-runtime 可以帮我们把直接写入文件里工具函数变成对 core-js 的引用,可以减少转译后的文件大小。

使用场景

从上面的定位可以看出,@babel/plugin-transform-runtime@babel/preset-env 并不重合,两者的功能没有交集。

对于任何需要考虑兼容性的项目,我们都应该使用 babel 进行转译,并使用 @babel/preset-env 降低配置的复杂度,大部分通用的配置如下:

module.exports = {
  'presets': [
    [
      '@babel/preset-env',
      {
        'corejs': 3, // 使用 core-js@3 版本,core-js@2 从 ES2017 之后就没再更新了,不推荐使用
        'useBuiltIns': 'usage', // 只转译用到的新语言元素
        'bugfix': true, // v7.9 之后引入的新选项,尽量减小转译后的代码体积,v8 之后会变成默认选项
      },
    ],
  ],
};

小型项目可以到此为止,中大型项目、文件数量比较多的,可以引入 @babel/plugin-transform-transform。此时我们需要先安装两个依赖——注意,这俩依赖都要装:

# 用来开发、debug 和编译
npm i @babel/plugin-transform-runtime -D

# 用来在生产环境中使用
npm i @babel/runtime
# 如果要使用特定的 core-js 版本,也可以安装特定的 runtime
npm install --save @babel/runtime-corejs2
npm install --save @babel/runtime-corejs3

接下来,修改上面的 babel.config.js,加入插件配置:

module.exports = {
  // 重复上面的配置
  "plugins": [
    // 其它插件
    [
      "@babel/plugin-transform-runtime",
      // 一般情况下我们使用默认配置即可
    ],
  ],
};

完成。

库项目

库类项目也推荐使用 @babel/plugin-transform-runtime,因为库项目通常会面临另一个问题。如果我们直接导入 core-js 作 polyfill 的话,像 PromiseSetMap 这样的全局对象就会被覆盖。对于一般的应用而言,问题不大;但如果是库,你无法预期其它开发者会在什么情况下使用你的库,很可能他的目标平台都支持这些新语法元素,不希望转译污染。

此时,使用 @babel/plugin-transform-runtime 可以让 babel 在转译时使用沙箱包装 polyfill,避免污染全局。

参考文档

meathill

爱编程,爱旅游,爱吐槽。
今年的目标是完成并运营至少一个 Side Project。
《Electron + Vue 实战开发》龟速创作中……

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据