专栏名称: Fundebug
Fundebug为JavaScript、微信小程序及Node.js开发团队提供专业的线上代码bug监控和智能分析服务。
目录
相关文章推荐
前端大全  ·  10年了,开发人员仍然不明白 ... ·  16 小时前  
前端早读课  ·  【招聘】字节跳动客服平台招高级前端开发工程师 ·  20 小时前  
前端早读课  ·  【第3455期】快手主站前端工程化探索:Gu ... ·  20 小时前  
歸藏的AI工具箱  ·  终于有给设计师用的 Cursor 了 ·  昨天  
歸藏的AI工具箱  ·  终于有给设计师用的 Cursor 了 ·  昨天  
前端早读课  ·  【开源】TinyEngine开启新篇章,服务 ... ·  2 天前  
51好读  ›  专栏  ›  Fundebug

关于Babel配置项的这点事

Fundebug  · 公众号  · 前端  · 2018-11-01 09:06

正文

摘要: IE虽然没落了,Babel还是要用的…

  • 原文: 关于Babel配置项的这点事

  • 作者: tonyc726

Fundebug经授权转载,版权归原作者所有。

Babel 作为一个JavaScript的语法编译器,可以将 ES6/7/8 代码转为 ES5 代码,从而在现有环境执行。

但是初次配置 .babelrc 的时候,各种 presets plugins 看的眼花缭乱,不知道如何下手,下面就自己学习Babel时遇到的问题做一下总结:

如果你是初次接触babel,推荐阅读阮一峰的《 Babel 入门教程

Plugin、Preset、Stage-X的关系

按照Babel官网的 介绍 ,其实Preset和Stage-X都是归属到Plugin里面的,只不过所覆盖的范围不同而已。

举个例子,如果需要转换ES2015(ES6)的语法,那么你可以在 .babelrc plugins 中按需引入 check-es2015-constants es2015-arrow-functions es2015-block-scoped-functions 等等几十个不同作用的plugin:

// .babelrc
{
 "plugins": [
   "check-es2015-constants",
   "es2015-arrow-functions",
   "es2015-block-scoped-functions",
   // ...
 ]
}

但是Babel团队为了方便,将 同属ES2015的几十个Transform Plugins 集合到 babel-preset-es2015 一个Preset中,这样你只需要在 .babelrc presets 加入 es2015 一个配置就可以完成全部ES2015语法的支持了:

// .babelrc
{
 "presets": [
   "es2015"
 ]
}

另外,不论是Plugin还是Preset,有不少都有单独属于自己的配置项,具体如何操作的可以看一下 官网的说明

上面介绍了Plugin与Preset,那么Stage-X就很好理解了, stage-0 stage-1 stage-2 stage-3 stage-4 分别对应的就是进入标准之前的5个阶段,不同 stage-x 之间存在依赖关系,数字越小,阶段越靠后,靠后阶段包含前面阶段所有的功能,简单理解就是 stage-0 包含 stage-1/2/3 的内容,所以如果你不知道需要哪个 stage-x 的话,直接引入 stage-0 就好了。

PS: babel-preset-stage-4 已经整合入Presets不单独发布了。

以上就是一些基础概念,目前,官方推荐使用 babel-preset-env ,它可以根据你的配置结合 compat-table 来帮你自动引入你需要的plugins,它有很多 配置项 ,下面介绍几个常用的:

  • targets: { [string]: number | string } ,默认 {}

需要支持的环境,可选例如: chrome , edge , firefox , safari , ie , ios , node ,甚至可以指定版本,如 node: "6.10" 或者 node: "current" 代表使用当前的版本;

  • targets.node: number | string | "current" | true

指定 node 的版本,例如: 6.10

  • targets.browsers: Array | string

指定需要兼容的浏览器清单,具体参考 browserslist ,例如: ["last 2 versions", "safari >= 7"]

例如需要配置兼容 ["last 2 versions", "safari >= 7"] babel-preset-env

// .babelrc
{
 "presets": [
   ["env", {
     "targets": {
       "browsers": ["last 2 versions", "safari >= 7"]
     }
   }]
 ]
}

此外,不同的plugins和presets或许有些功能是重复的,有些存在依赖关系,在配置的时候还有前后顺序的不同,那么Babel在运行的时候是怎么处理的呢?总结一下,规律大概有以下几点:

  • plugins优先于presets进行编译;

  • plugins按照数组的index增序(从数组第一个到最后一个)进行编译;

  • presets按照数组的index倒序(从数组最后一个到第一个)进行编译,因为作者认为大部分会把presets写成 ["es2015", "stage-0"] ,具体细节可以看 这个

摘自《 如何写好.babelrc?Babel的presets和plugins配置解析

babel-polyfill与babel-runtime的选择

Babel默认只转换新的JavaScript语法,而不转换新的API,比如 Iterator Generator Set Maps Promise 等等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign )都不会转码,具体的可以参考 babel-plugin-transform-runtime 模块的 definitions.js 文件。

babel-polyfill babel-runtime 就是为了解决这种全局对象或者全局对象方法不足的问题,而诞生的2种解决方式。

当然,你还可以用 promise-polyfill 此类Polyfill解决全局对象的问题;
或者用
lodash 此类Utils解决 Object.assign 这种方法扩展的问题。

先说说 babel-polyfill ,它的做法比较暴力,就是将全局对象通通污染一遍,这样做的坏处有几点:

  1. 可能会增加很多根本没有用到的polyfill;

  2. 可能会污染子模块的局部作用域,严重的或许会导致冲突;

但是,这样做也有好处,如果你的运行环境比较low,比如说Android一些老机子,而你有需要大量使用 Promise Object.assign Array.find 之类的全局对象或者其所属方法,那么使用 babel-polyfill ,绝对是一劳永逸。

接着,再来说说 babel-runtime ,相对而言,它的处理方式比较温柔,套用步步高的广告词就是哪里需要加哪里,比如说你需要 Promise ,你只需要 import Promise from 'babel-runtime/core-js/promise' 即可,这样不仅避免污染全局对象,而且可以减少不必要的代码。

不过,如果N个文件都需要 Promise ,难道得一个个文件的加 import Promise from 'babel-runtime/core-js/promise' 么,显然不是,Babel已经为这样情况考虑过了,只需要使用 babel-plugin-transform-runtime 就可以轻松的帮你省去手动 import 的痛苦,而且,它还做了公用方法的抽离,哪怕你有100个模块使用了 Promise ,但是promise的polyfill仅仅存在1份,所有要的地方都是引用一地方,具体的配置参考如下:

// .babelrc
{
 "presets": [
   "env",
   "stage-0"
 ],
 "plugins": [
   "transform-runtime"






请到「今天看啥」查看全文