跳到主要内容

preset-env

2023年12月21日
柏拉文
越努力,越幸运

一、认识


旧版浏览器的语法兼容问题主要分两类: 语法降级问题和 Polyfill 缺失问题。前者比较好理解,比如某些浏览器不支持箭头函数,我们就需要将其转换为 function(){} 语法;而对后者来说,Polyfill本身可以翻译为垫片,也就是为浏览器提前注入一些 API 的实现代码,如 Object.entries 方法的实现,这样可以保证产物可以正常使用这些 API,防止报错。

这两类问题本质上是通过前端的编译工具链(如Babel)及 JS 的基础 Polyfill 库(如corejs)来解决的,不会跟具体的构建工具所绑定。

1.1 useBuiltIns: entry

useBuiltIns: entry 声明 Polyfill 策略为 entry, entry 配置规定你必须在入口文件手动添加一行这样的代码:

import 'core-js';

Babel 所做的事情就是将你的 import "core-js" 代码替换成了产物中的这些具体模块的导入代码。这个配置有一个问题,即无法做到按需导入,上面的产物代码其实有大部分的 Polyfill 的代码我们并没有用到。

1.2 useBuiltIns: usage

useBuiltIns: usage 真正地实现了按需 Polyfill 导入

1.3 preset-env polyfill

利用 @babel/preset-env 进行了 目标浏览器语法的降级Polyfill 注入,同时用到了 core-jsregenerator-runtime两个核心的运行时库。但 @babel/preset-env 的方案也存在一定局限性:

  • 如果使用新特性,往往是通过基础库(如 core-js)往全局环境添加 Polyfill,如果是开发应用没有任何问题,如果是开发第三方工具库,则很可能会对全局空间造成污染。

  • 很多工具函数的实现代码(如上面示例中的_defineProperty方法),会在许多文件中重现出现,造成文件体积冗余。

二、安装


安装必要编译时依赖:

pnpm install @babel/cli @babel/core @babel/preset-env -D
  • @babel/cli: 为 babel 官方的脚手架工具

  • @babel/core: babel 核心编译库。

  • @babel/preset-env: babel 的预设工具集,基本为 babel 必装的库。

安装必要运行时依赖: Polyfill 代码主要来自 core-jsregenerator-runtime,因此如果要运行起来,必须要装这两个库。

pnpm i core-js regenerator-runtime -S
  • core-js

  • regenerator-runtime

三、配置


3.1 .browserslistrc

Browserslist 是一个帮助我们设置目标浏览器的工具,不光是 Babel 用到,其他的编译工具如postcss-preset-envautoprefix中都有所应用。对于 Browserslist 的配置内容,你既可以放到 Babel 这种特定工具当中,也可以在package.json中通过browserslist声明:

ie >= 11

3.2 babel.config.js

useBuiltIns: "entry"

export default {
presets: [
[
'@babel/preset-env',
{
corejs: 3,
modules: false,
useBuiltIns: "entry"
}
]
],
};

useBuiltIns: "usage"

export default {
presets: [
[
'@babel/preset-env',
{
corejs: 3,
modules: false,
useBuiltIns: "usage"
}
]
],
};

四、测试


4.1 index.js

// 如果 useBuiltIns: "entry" , 需要引入 import "core-js"

const func = async ()=>{
console.log("Hello World!")
}

func();

Promise.resolve().finally();

4.2 命令行输入

npx babel ./index.js --out-dir dist 使用 Babel 进行编译

效果如下:

Preview