title | date | status |
---|---|---|
深入理解babel |
2017-09-21 |
finished |
基于最新的ECMAScript将JS编译成在各个平台、各种版本的浏览器上都能运行的代码。它是js编译器。
babel从V6.0开始使用模块化,将所有功能以插件形式分离出来,默认只提供babel-core。使用更加灵活
以命令行的方式用babel编译js
以编程的形式用babel编译js
简单的运行babel,只是输出了原样js,并没有按照预期的编译js。此时需要安装并配置插件(plugins)或预设(presets)来告诉babel如何编译。
插件(plugins):是单一的功能,例如,
es2015-arrow-functions
、es2015-classes
。
预设(presets):是一组插件。
配置一般有两种方式:
- package.json 中的babel属性
- .babelrc文件
项目根目录创建.babelrc
,一般有以下配置项:
{
"presets": [],
"plugins": [],
}
打包了一系列es6特性的插件。当然还有babel-preset-2016,babel-preset-2017。
{
"presets": [
"es2015"
],
"plugins": [],
}
为了让babel插件编译比较精简,这个预设可以声明编译环境,把js编译到满足声明的环境即可。配置官方文档说明: http://babeljs.io/docs/plugins/preset-env/
{
"presets": [
"env", {
"target": {
"node": "6.10",
"browsers": "> 5%",
"chrome": 56
}
}
],
}
http://babeljs.io/docs/plugins/
stage-x预设中的任何js规范的变化都是没有被正式发布的。
js的标准规范是通过提草案到具体实现这一个一个阶段确定的。
官方预设有两种形式,按照年份
babel-preset-2017
、按照阶段babel-preset-stage-0
这是根据TC39 委员会ECMASCRPIT 发布流程来制定的。TC39 委员会决定,从2016年开始,每年都会发布一个版本,它包括每年期限内完成的所有功能,同时ECMAScript的版本号也按年份编制,就有了ES2016, ES2017
TC39将建议分为以下几个阶段:
- Stage 0 - 稻草人: 只是一个想法,可能的Babel插件
- Stage 1 - 提案:值得的做的
- Stage 2 - 草案:初始规则
- Stage 3 - 候选:完整的规范和初始浏览器实现。
- Stage 4 - 完成:将被添加到下一年度发行。 最终在阶段 4 被标准正式采纳。
所以一般数值越小的内容,会包含数字大的。
有了一些常用plugins、presets之后,那如何运用plugins、presets编译js呢?官方有两种解决方案:babel-runtime+ babel-plugin-transform-runtime、 babel-polyfill。其目的都是为了模拟ES2015环境,补充API,编译js,但是实现方式不同。
babel-polyfill通过全局声明API函数来进行js转换,容易造成全局污染。 babel-runtime 是通过手动引入helper函数。但是这种方式不能实现重复helper函数的的共享。 babel-plugin-transform-runtime基于babel-runtime将重复的helper函数抽离成模块
http://babeljs.io/docs/usage/polyfill/
polyfill: 代码填充或兼容性补丁。
在js全局补充还不存在的API功能函数,这样会覆盖运行环境提供的函数,造成全局污染。
它主要包括两个方面:
- regenerator runtime 可以在js总用generators、async functions
- core-js
npm install --save babel-polyfill
- 在node、webpack、browserify环境下引入:
require("babel-polyfill")
; - 在browser环境下:直接引入资源。
- 在一些环境下,可以直接引用用到的polyfill
它和babel-polyfill类似,不同的是它可以单独在js模块中引用,例如: require(‘babel-runtime/core-js/promise’)
。这样不会造成全局污染。
但是手动引入比较低效,可以借助babel-plugin-transform-runtime自动化引入。
npm install --save-dev babel-plugin-transform-runtime
(这只是一个工具)
npm install --save babel-runtime
(和babel-polyfill一样是js功能函数)
http://babeljs.io/docs/plugins/transform-runtime/#technical-details
- 当使用generators/async functions,自动依赖
babel-runtime/regenerator
。 - 自动依赖
babel-runtime/core-js
并匹配ES6静态方法和内置方法。 - 用
babel-runtime/helpers
模块替换babel行内的helpers。(增加helpers函数的复用)。
具体实现包括
- regenerator 重命名
- corejs函数重命名
- helper重命名
宽松模式,很多转换器都有“宽松”模式,通过放弃一些标准中的行为来生成更简化且性能更好的代码。
{
"plugins": [
"transform-runtime",
["transform-es2015-classes", { "loose": true }]
]
}
http://babeljs.io/docs/plugins/#plugin-preset-ordering
- Plugins优先于Presets
- Plugin是从左至右执行
- Presets是从又至左执行
- 这是为了向后兼容,因为很多用户的编写方式是
["stage-0","es2015" ]
- 这是为了向后兼容,因为很多用户的编写方式是
请参考官方文档:http://babeljs.io/docs/plugins/#plugin-development
https://segmentfault.com/a/1190000008159877
https://github.com/thejameskyle/babel-handbook/blob/master/translations/zh-Hans/user-handbook.md