@babel/preset-env相关问题

刚接触bable的同学会犯一个错误,认为在使用了Babel后就可以畅快的使用 es2015 了,事实上Babel只能转换语法(如箭头函数、let、const、class等),像Promise 、Async、Object.assign、Array.find()等api是依赖浏览器实现的,想在不支持的浏览器上使用新的API,需要采用Polyfill技术,实现Polyfill有多种方式,方式对比请点我

Babel 推荐使用 @babel/preset-env 套件来处理转译需求。顾名思义,preset 即“预制套件”,包含了各种可能用到的转译工具。之前的以年份为准的 preset 已经废弃了,现在统一用这个总包。同时,babel 已经放弃开发 stage-* 包,以后的转译组件都只会放进 preset-env 包里。

一、重要参数

1. target

@babel/preset-env 支持一些参数,用来处理哪些 feature 要转译,哪些不要。其中比较重要的是 targets,用来指定目标环境。targets 使用 browserslist 来筛选浏环境,这样我们就不需要指定所有浏览器版本,而可以使用类似 last 2 versions 这样的描述。具体怎写,可以看文档,这里不再赘述。

如果你想知道自己配置的是否合适,可以在仓库目录下执行 npx browserslist,列出所有目标浏览器。

Babel 官方建议我们把 targets 写到 .browserslistrc 或者 package.json 里,不然除了babel外,其他的工具,例如browserslist等无法从 .babelrc 等 babel 配置文件里读取配置。

2. useBuiltIns

接下来,我们可以配置 useBuiltIns这个属性决定是否引入 polyfill。它有三个可选值:

false,不引入,或者说,Babel 编译结果不引入。把引入的位置、引入哪些 polyfill 交给用户处理。

entry, 开发者在核心入口文件中使用 import '@babel/polyfill' 语句引入,其实并不理想,因为大部分浏览器不需要这些。

usage, 即“按需引用”。如果目标浏览器(从target中知道目标浏览器)不支持需要的 feature,那么就自动引入 polyfill,不然的话就不引用。由于目前的打包工具越发智能,随着 tree shaking 的完善,这样可以最低限度引入 polyfill。

3. corejs

core-js 目前最新版本是 3.0.1,关于 v3 和 v2 的对比,大家可以看这篇博文:https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md。这里简单总结一下,core-js 2 封版于 1.5 年之前,所以里面只有对 1.5 年之前 feature 的 polyfill,最近 1.5 年新增的 feature 都不支持,也就存在因为新功能没有 polyfill 于是在旧浏览器里失败的风险。

所以我们应当升级到最新版,npm i core-js@3 -D 然后修改 babel 配置

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 5%",
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

此选项仅在与useBuiltIns:usage或useBuiltIns:entry一起使用时有效,并确保@babel/preset env为您的核心js版本注入正确的导入。

默认情况下,corejs只会使用已确定的ECMAScript进行polyfill:如果要使用stage-1(proposal)的polyfill,有三个不同的选项 :

当使用useBuiltIns:“entry”时,可以直接导入一个建议polyfill:import“core js/propositions/string replace all”。

使用useBuiltIns:"usage"时:“用法”有两种不同的选择:

    将shippedprovals选项设置为true。这将使polyfills和proposition转换成为可能,这些建议已经在浏览器中发布了一段时间。 

    使用corejs:{version:3,propositions:true}。这将使核心js支持的每一个提案都能实现多元化。 

备注: TC39 将提案分为以下几个阶段:

  • Stage 0 - 设想(Strawman):只是一个想法,可能有 Babel插件。
  • Stage 1 - 建议(Proposal):这是值得跟进的。
  • Stage 2 - 草案(Draft):初始规范。
  • Stage 3 - 候选(Candidate):完成规范并在浏览器上初步实现。
  • Stage 4 - 完成(Finished):将添加到下一个年度版本发布中。

有关详细信息,请务必查看 current TC39 proposals 及其 process document

TC39 各阶段的流程也在一些文章中有详细的解释,在 Yehuda Katz (@wycatz) 的 thefeedbackloop.xyz网站上:Stage 0 and 1Stage 2Stage 3

二、@babel/polyfill

@babel/polyfill 是对 core-js 的封装,引入该库时,实际上是引用了 core-js 的内容和生成器(regenerator-runtime)。 v7.4 之后,这个仓库就被废弃了,希要用户自己选择使用哪个兼容库。

换言之,以前是这么引用的:

import "@babel/polyfill";

现在需要:

import "core-js/stable";
import "regenerator-runtime/runtime";

对于绝大部分情况,使用 @babel/preset-env + useBuiltIns: 'usage' 仍然是最好的选择。

原文地址:https://www.cnblogs.com/94pm/p/13751728.html