文章概览

babel-preset-env是非常重要且常用的一个插件预设,掌握它的用法以及实现原理非常有必要。

本文主要内容包括:babel-preset-env是什么、入门实例、如何配置以支持特定版本的 node/浏览器、实现原理等。

本文所有例子可以在 笔者的github 找到。

babel-preset-env简介

首先,介绍下历史背景,对了解和学习 babel-preset-env 有帮助。

最初,为了让开发者能够尽早用上新的JS特性,babel团队开发了babel-preset-latest。这个preset比较特殊,它是多个preset的集合(es2015+),并且随着ECMA规范的更新更增加它的内容。

比如,当前(2018.06.02),它包含的preset包括:es2017、es1016、es2015。

到了明年,可能它包含的preset就包括:es2018、es2017、es2016、es2015。

随着时间的推移,babel-preset-latest 包含的插件越来越多,这带来了如下问题:

  1. 加载的插件越来越多,编译速度会越来越慢;
  2. 随着用户浏览器的升级,ECMA规范的支持逐步完善,编译至低版本规范的必要性在减少(比如ES6 -> ES5),多余的转换不单降低执行效率,还浪费带宽。

因为上述问题的存在,babel官方推出了babel-preset-env插件。它可以根据开发者的配置,按需加载插件。配置项大致包括:

  1. 需要支持的平台:比如node、浏览器等。
  2. 需要支持的平台的版本:比如支持node@6.1等。

默认配置的情况下,它跟 babel-preset-latest 是等同的,会加载从es2015开始的所有preset。

入门例子

首先,安装依赖。

npm install babel-cli --save-dev
npm install babel-preset-env --save-dev

创建 index.js。

let foo = () => 'foo';

配置文件 .babelrc 如下,当前为默认配置。

{
"presets": [ "env" ]
}

运行转换命令

`npm bin`/babel index.js

转换结果如下:

'use strict';

var foo = function foo() {
return 'foo';
};

针对node版本的配置

前面提到,babel-preset-env 提供了更精细化的配置,以提升编译速度,同时减少代码冗余。

我们看下实际例子。假设当前有如下代码:

// index.js
async function foo () {}

采用 babel-preset-env,默认配置下,输出的转换结果如下(具体内容不用关心,知道很长就行了)。

"use strict";

var foo = function () {
var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
case "end":
return _context.stop();
}
}
}, _callee, this);
})); return function foo() {
return _ref.apply(this, arguments);
};
}(); function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

如果我们的代码是打算跑在node@8.9.3版本上,那上面的兼容代码就有点多余了,因为node@8.9.3已经支持了async/await。

修改下 .babelrc,加上配置参数"target",它表示我们需要支持哪些平台+哪些版本。这里声明我们要支持的是node版本为8.9.3。

{
"presets": [
["env", {
"targets": {
"node": "8.9.3"
}
}]
]
}

再次进行转码,结果如下。几乎没有变化,因为node最新版本支持 async/await,因此不需要额外的兼容代码。

"use strict";

async function foo() {}

针对浏览器版本的配置

babel-preset-env 同样提供了对浏览器版本的配置能力。

支持特定版本的浏览器

假设我们的代码如下:

let nick = '程序猿小卡';
let desc = `你好 ${nick}`;

如果只需要支持 IE11,那么可以这样配置。

{
"presets": [
["env", {
"targets": {
"browsers": "ie 11"
}
}]
]
}

如果只需要支持支持 Edge 16,那么可以这样配置

{
"presets": [
["env", {
"targets": {
"browsers": "edge 16"
}
}]
]
}

因为 IE 11 不支持模板字面量,而 Edge 16支持模板字面量,因此上面配置的转码结果是不同的,读者可以自行尝试。

支持特定版本范围的浏览器

大部分时候,我们要针对的都是特定范围的浏览器,比如 IE8+,那么,逐个指定是不现实的。好在 babel-preset-env 支持要支持的版本范围。

比如,我们需要支持 IE8+、chrome62+,那么可以这样配置:

{
"presets": [
["env", {
"targets": {
"browsers": [ "ie >= 8", "chrome >= 62" ]
}
}]
]
}

看下前面声明的范围涵盖了哪些浏览器。

$ `npm bin`/browserslist "ie >= 8, chrome >= 62"
chrome 66
chrome 65
chrome 64
chrome 63
chrome 62
ie 11
ie 10
ie 9
ie 8

对浏览器版本范围的配置,babel-preset-env 借助了 browserslist 这个库,还有更多的配置方式,可以自行探究。

babel-preset-env实现原理

实现原理很简单。官方文档写的挺简洁的,挑重点大致翻译下。

1、首先,检测浏览器对JS特性的支持程度,比如通过通过 compat-table 这样的外部数据。

2、将 JS特性 跟 特定的babel插件 建立映射,映射关系可以参考 这里

3、stage-x 的插件不包括在内。

4、根据开发者的配置项,确定至少需要包含哪些插件。比如声明了需要支持 IE8+、chrome62+,那么,所有IE8+需要的插件都会被包含进去。

相关链接

https://babeljs.io/docs/plugins/preset-env/#how-it-works

babel-preset-env使用指南的更多相关文章

  1. babel 7 简单升级指南

    babel 7 babel 7 发布两天了,试着对当前项目更新了下,仅此记录分享 主要改动参考 官方博客 官方升级指南 主要升级内容 不再支持放弃维护的 node 版本 0.10.0.12.4.5 使 ...

  2. Error: Couldn't find preset "env" relative to directory "/Users/user/ethereumjs-vm"

    运行npm run build时遇见这个问题,解决办法是安装: npm install --save-dev babel-preset-env 就解决了

  3. vue客户端渲染首屏优化之道

    提取第三方库,缓存,减少打包体积 1. dll动态链接库, 使用DllPlugin DllReferencePlugin,将第三方库提取出来另外打包出来,然后动态引入html.可以提高打包速度和缓存第 ...

  4. babel-preset-env: a preset that configures Babel for you

    转载 babel-preset-env is a new preset that lets you specify an environment and automatically enables t ...

  5. 《前端之路》之 Babel 下一代 JavaScript 语法编译器

    写本章的内容的出发点主要是 为了对于之前关于 JS 版本的一个总结,在之前的开发中,我们始终对于 ECMAScript 的版本的更新不够重视,以至于在后面的 开发过程中,我们始终会被各种新奇的语法打断 ...

  6. 你必须要知道的babel二三事

    1. 什么是babel 本文基于的babel版本是7.11.6,本文所有示例github Babel is a toolchain that is mainly used to convert ECM ...

  7. WebStorm ES6 语法支持设置&babel使用及自动编译

    一.语法支持设置 Preferences > Languages & Frameworks > JavaScript 二.Babel安装 1.全局安装 npm install -g ...

  8. babel基本用法

    babel-cli babel-cli是本地使用编译js文件 1.安装: cnpm i babel-cli babel-preset-env -D 2.配置packjson: "script ...

  9. webpack中babel配置 --- runtime-transform和babel-pollfill

    webpack - babel配置 babel是一个javascript编译器,是前端开发中的一个利器.它突破了浏览器实现es标准的限制,使我们在开发中可以使用最新的javascript语法. 通过构 ...

  10. Babel总结

    什么是babel? babel是一个JavaScript编译器. Babel是一个工具链,主要用于将ECMAScript 2015+代码转换为向后兼容的旧浏览器或环境中JavaScript版本. 注解 ...

随机推荐

  1. JHipster生成微服务架构的应用栈(五)- 容器编排示例

    本系列文章演示如何用JHipster生成一个微服务架构风格的应用栈. 环境需求:安装好JHipster开发环境的CentOS 7.4(参考这里) 应用栈名称:appstack 认证微服务: uaa 业 ...

  2. 服务器CPU繁忙或内存压力引起网络掉包的浅析与总结

      最近一段时间遇到了两起有意思的故障,现象都是网络掉包或网络断开,不过这些只是表面现象,引起现象出现的本质才是我们需要关注的重点: 案例1: 平台   :VMware平台 操作系统 :Windows ...

  3. 反射生成 INSERT 多个对象的 SQL 语句(批量插入)

    + View code private static void insertObject(List<?> objectList) throws IllegalAccessException ...

  4. powersploit的用法

    一.PowerSploit简介 PowerSploit是GitHub上面的一个安全项目,上面有很多powershell攻击脚本,它们主要被用来渗透中的信息侦察.权限提升.权限维持. Powershel ...

  5. 【Linux基础】大B和小b

    1.小b(bit) 在计算机科学中,bit(比特)是表示信息的最小单位,叫做二进制位,一般用0和1表示. 2.大B(Byte) Byte叫做字节,由8个位(8bit)组成一个字节(1Byte),用于表 ...

  6. (转)Spring Boot 2 (二):Spring Boot 2 尝鲜-动态 Banner

    http://www.ityouknow.com/springboot/2018/03/03/spring-boot-banner.html Spring Boot 2.0 提供了很多新特性,其中就有 ...

  7. 【ZJOI2016】线段树

    [ZJOI2016]线段树 ZJOI的题神啊. 我们考虑计算每个位置\(p\),它在操作过后变成第\(x\)个数的操作序列数. 我们枚举\(x\).我们先得到了\(L_x,R_x\)表示最左边比\(x ...

  8. 设计模式のSingleton Pattern(单例模式)----创建模式

    单例模式没有什么好讲的,我们 举个例子 #region 单例定义 /// <summary> /// 类单例 /// </summary> private static Win ...

  9. python学习初始函数

    函数的用途:解决代码的冗余.可读性差.可扩展性差. 函数的一般格式: #函数定义 def mylen(): """计算s1的长度""" s1 ...

  10. 在 PHP 7 中不要做的 10 件事

    在 PHP 7 中不要做的 10 件事 1. 不要使用 mysql_ 函数 这一天终于来了,从此你不仅仅“不应该”使用mysql_函数.PHP 7 已经把它们从核心中全部移除了,也就是说你需要迁移到好 ...