@babel/preset-env和@babel/plugin-transform-runtime傻傻分不清

前言

babel只是转换语法,后为了解决API的兼容,又引入了pollify概念,再后来为了解决组件开发者的环境多样性,又引入了runtime。

本文以async、Promise、Array.prototype.includes三个方法如何运行在IE9中作为例子,粗略探讨两者之间的差别和使用。
详见官网

环境

为了清晰直观,本文采用两种方式编译

  • @babel/cli
    直接编译代码,更清晰看到babel帮我们引入了什么
  • rollup
    将代码编译成浏览器可运行代码,验证结果
  //package.json
  "devDependencies": {
    "@babel/cli": "^7.18.10",
    "@babel/core": "^7.18.10",
    "@babel/plugin-transform-runtime": "^7.18.10",
    "@babel/preset-env": "^7.18.10",
    "rollup": "^2.6.1",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-node-resolve": "^5.2.0"
  },
  "dependencies": {
    "@babel/runtime": "^7.18.9",
    "@babel/runtime-corejs3": "^7.18.9",
    "core-js": "^2.6.12"
  }
//rollup.config.js
import resolve from 'rollup-plugin-node-resolve';   //帮助rollup查找外部模块,然后导入
import babel from 'rollup-plugin-babel';            
import commonjs from 'rollup-plugin-commonjs';      //将CommonJS模块转换为ES2015供rollup处理

export default {
    input: './a.js',
    output: {
        file: './b.js',
        format: 'iife'
    },
    plugins: [
        resolve(),
        babel({
            exclude: 'node_modules/**',
            runtimeHelpers: true      //启用babel runtime
        }),
        commonjs({})
    ]
};

preset-env

说明

preset-env本身只解决了语法层面的问题,配合polyfill(polyfill是一个统称,常见的包括@babel/polyfill和core-js等)可以解决api兼容问题
@babel/core 7.4.0后polyfill被废弃,被core-js/stable代替(因为@babel/polyfill的核心就是core-js)
来自官方:

As of Babel 7.4.0, this package has been deprecated in favor of directly including core-js/stable (to polyfill ECMAScript features)

特别注意
如果要转换generator或者async,当@babel/core版本小于7.18.0时,需要自行加载regenerator-runtime
来自官方:

If you are compiling generators or async function to ES5, and you are using a version of @babel/core or @babel/plugin-transform-regenerator older than 7.18.0, you must also load the regenerator runtime package. It is automatically loaded when using @babel/preset-env's useBuiltIns: "usage" option or @babel/plugin-transform-runtime

配置

useBuiltIns

有三个值可选

false

不需要导入core-js
不用polyfill,如果入口文件中导入了core-js, 会无视targets的配置加载所有的 polyfill

entry

需要在入口文件中导入core-js

// a.js
import "core-js/stable";

(async () => {
    const arr = await Promise.resolve([1,2,3]);
    console.log(arr.includes(2));
})();
// .babelrc
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "debug": true,
                "useBuiltIns": "entry",
                // "corejs": {      //默认version为2,使用3需要安装core-js@3
                //     "version": "3"
                // },
                "targets":{
                    "browsers":["ie >= 9"]
                }
            }
        ]
    ]
}
直接编译,执行命令:
npx babel a.js -o b.js

b.js结果如下:

image.png

可以看到babel导入了基于targets配置所有不支持的全部特性,并且注入了helper函数

rollup编译,执行命令:
npm run build

Edge中模拟IE9顺利打印出true

usage

需要在入口文件中导入core-js(a.js同上)

// .babelrc
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "debug": true,
                "useBuiltIns": "usage",
                // "corejs": {      //默认version为2,使用3需要安装core-js@3
                //     "version": "3"
                // },
                "targets":{
                    "browsers":["ie >= 9"]
                }
            }
        ]
    ]
}
直接编译,执行命令:
npx babel a.js -o b.js

b.js结果如下:


image.png

可以看到babel只导入了基于targets配置且在代码中使用到的特性,并且注入了helper函数

rollup编译,执行命令:
npm run build

Edge中模拟IE9顺利打印出true

plugin-transform-runtime

说明

plugin-transform-runtime配和runtime使用可以按需引入特性,并且挂载在内建变量中,不污染全局,特别适合组件开发者使用。

runtime

组成

runtime包含了helper 的 runtime 版本,corejs,和实现 async、await 的regenerator
runtime 这3部分除了 helper 其他都是第三方的

作用

  • 自动移除语法转换后内联的辅助函数(inline Babel helpers),使用@babel/runtime/helpers里的辅助函数来替代;

  • 当代码里使用了core-js的API,自动引入@babel/runtime-corejs3/core-js-stable/,以此来替代全局引入的core-js/stable;

  • 当代码里使用了generator/async函数,自动引入@babel/runtime/regenerator,以此来替代全局引入的regenerator-runtime/runtime;

到这儿你应该知道了,plugin-transform-runtime其实是preset-env的增强

特别注意
corejs2仅支持全局变量和静态属性polyfill(例如:Promise和Array.from),要兼容incluedes等实例属性需要用到corejs3

corejs option Install command
false npm install --save @babel/runtime
2 npm install --save @babel/runtime-corejs2
3 npm install --save @babel/runtime-corejs3

配置

corejs

不需要导入core-js

// a.js
(async () => {
    const arr = await Promise.resolve([1,2,3]);
    console.log(arr.includes(2));
})();
// .babelrc
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "debug": true,
                "targets":{
                    "browsers":["ie >= 9"]
                }
            }
        ]
    ],
    "plugins": [
        [
            "@babel/plugin-transform-runtime",
            {
                "corejs": "3"
            }
        ]
    ]
}
直接编译,执行命令:
npx babel a.js -o b.js

b.js结果如下:


image.png

可以看到内联的helper函数都被@babel/runtime-corejs3/helpers/替换,并且只导入了基于targets配置且在代码中使用到的特性

rollup编译,执行命令:
npm run build

Edge中模拟IE9顺利打印出true

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容