@babel/preset-env相关问题
Babel 推荐使用 @babel/preset-env 套件来处理转译需求。顾名思义,preset 即“预制套件”,包含了各种可能用到的转译工具。
之前的以年份为准的 preset 已经废弃了,现在统一用这个总包。同时,babel 已经放弃开发 stage-* 包,以后的转译组件都只会放进 preset-env 包里。
@babel/preset-env默认会支持stage4的特性转换(当然是针对@babel/preset-env当前版本发布年份的stage4提案)。
一、重要参数
1. target
@babel/preset-env 支持一些参数,用来处理哪些 feature 要转译,哪些不要。其中比较重要的是 targets
,用来指定目标环境。targets
使用 browserslist 来筛选浏环境,这样我们就不需要指定所有浏览器版本,而可以使用类似 last 2 versions
这样的描述。具体怎写,可以看文档,这里不再赘述。
如果你想知道自己配置的是否合适,可以在仓库目录下执行 npx browserslist
,列出所有目标浏览器。
Babel 官方建议我们把 targets
的内容保存到 .browserslistrc文件中
或者 package.json
里增加一个browserslist节点,不然除了babel外,其他的工具,例如browserslist、post-css等无法从 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只会使用stage2及更高阶段的特性:如果要使用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 将提案分为以下几个阶段:
stage0 strawman
任何讨论、想法、改变或者还没加到提案的特性都在这个阶段。只有TC39成员可以提交。
stage1 proposal
(1)产出一个正式的提案。 (2)发现潜在的问题,例如与其他特性的关系,实现难题。 (3)提案包括详细的API描述,使用例子,以及关于相关的语义和算法。
stage2 draft
(1)提供一个初始的草案规范,与最终标准中包含的特性不会有太大差别。草案之后,原则上只接受增量修改。 (2)开始实验如何实现,实现形式包括polyfill, 实现引擎(提供草案执行本地支持),或者编译转换(例如babel)
stage3 candidate
(1)候选阶段,获得具体实现和用户的反馈。此后,只有在实现和使用过程中出现了重大问题才会修改。 (1)规范文档必须是完整的,评审人和ECMAScript的编辑要在规范上签字。 (2)至少要在一个浏览器中实现,提供polyfill或者babel插件。
stage4 finished
(1)已经准备就绪,该特性会出现在下个版本的ECMAScript规范之中。。 (2)需要通过有2个独立的实现并通过验收测试,以获取使用过程中的重要实践经验。
有关详细信息,请务必查看 current TC39 proposals 及其 process document。
二、@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'
仍然是最好的选则。
三、babel体系化教程
这个博文讲得非常好,完整并且成体系,建议阅读