1.Babel是什么
“The compiler for writing next generation JavaScript”
简单翻译下就是“用于编写下一代JavaScript的编译器”。随着时间推移,JavaScript也在慢慢进化,新的特性和语法随之出现,然而各个浏览器厂商并没有完全的支持,所以要有个工具,把新的特性和语法翻译成浏览器都认可的标准语法,Babel应运而生,它就是这个工具,ES6/ES7/ES8 => Babel => ES5。
babel-compile
2.Babel preset & plugin & stage-x
preset、stage-x都是plugin的范畴,只不过所覆盖的范围不同。如果你要用ES2015(ES6)语法,一下是plugin和preset的不同引入方式
(1)plugin
// .babelrc
{
plugins: [
'transform-class-properties',
'es2015-arrow-functions',
'transform-decorators-legacy'
]
}
(2)preset
为了大家引入方便,Babel团队将ES2015的很多个transform plugin集成到babel-preset-es2015,所以你这需要引入es2015,大大降低了引入成本
// .babelrc
{
"presets": [ "es2015" ]
}
(3)stage-x
stage-x分别代表的是stage-0、stage-1、stage-2、stage-3进入EMAC标准之前的4个阶段
(4)plugin和preset运行顺序
- plugin 会运行在preset之前
- plugin 会从第一个开始顺序执行
- preset 的顺序则刚好相反(从最后一个逆序执行)
3.babel-preset-es2015/es2016/es2017
(1)es2015(ES6)
- check-es2015-constants
- transform-es2015-arrow-functions
- transform-es2015-block-scoped-functions
- transform-es2015-block-scoping
- transform-es2015-classes
- transform-es2015-computed-properties
- transform-es2015-destructuring
- transform-es2015-duplicate-keys
- transform-es2015-for-of
- transform-es2015-function-name
- transform-es2015-literals
- transform-es2015-modules-commonjs
- transform-es2015-object-super
- transform-es2015-parameters
- transform-es2015-shorthand-properties
- transform-es2015-spread
- transform-es2015-sticky-regex
- transform-es2015-template-literals
- transform-es2015-typeof-symbol
- transform-es2015-unicode-regex
- transform-regenerator
(2)es2016(ES7)
- transform-exponentiation-operator
(3)es2017(ES8)
- syntax-trailing-function-commas
- transform-async-to-generator
4.babel-preset-stage-x
语言的变化需要一个过程来发展,stage-x提供了将一个想法进化为一种完善规范的指导原则,stage-0包含stage-1/2/3,stage-1包含stage-2/3,stage-2包含stage-3,TC39工作流:tc39.github.io/process-doc…
TC39
Process
(1)stage-0
- transform-do-expressions
- transform-function-bind
除了上述插件还包含stage-1,stage-2,stage-3的插件(2)stage-1
- transform-class-constructor-call (Deprecated)
- transform-export-extensions
除了上述插件还包含stage-2,stage-3的插件(3)stage-2
- syntax-dynamic-import
- transform-class-properties
- transform-decorators disabled pending proposal update (can use the legacy transform in the meantime)
除了上述插件还包含stage-3的插件(4)stage-3
- transform-object-rest-spread
- transform-async-generator-functions
5.babel-polyfill
Babel编译时只编译语法,并不会编译BOM不兼容的API,如:async ,Set,Symbol,Promise等,babel-polyfill会把这些没有的API全部挂载到全局对象,也就是所谓的“垫片”。
(1)优点
如果你代码中大量引用上述API,引入babel-polyfill将是一劳永逸
(2)缺点
babel-polyfill比较简单粗暴,在引入的同时,也污染了全局对象,导致无效增加了很多用不到的polyfill,也可能会污染子模块的变量引用,可能导致不必要的冲突。
- 如果你要使用babel-polyfill,你需要你其他代码或者模块被引用前引入,入口JS顶部(目前跟多情况下是在Node中使用):
// ES5
require("babel-polyfill");
// ES6
import "babel-polyfill";
6. babel-tuntime和babel-plugin-transform-runtime
(1)babel-runtime
babel-runtime和babel-polyfill有点类似,都是去兼容新API的“垫片”,它和babel-polyfill最大的不同就是可以做到按需引用,哪里需要什么就用什么,比如我需要Promise。一般在生成环境,首先安装依赖,然后引入:
npm install --save babel-runtime
import Promise from 'babel-runtime/core-js/promise';
(2)babel-plugin-transform-runtime
问题来了,如果用babel-runtime,如果我10个文件要引用Promise,难道每个文件都得写个babel-runtime的Promise引入么,显然很麻烦。那么babel-plugin-transform-runtime就是用来解决这个问题的,无论你多少个文件引入了相关新的API,它只会存在一份,babel-plugin-transform-runtime本质上依赖于babel-runtime的core-js,在编译的时候会帮你自动处理,在开发环境安装依赖:
npm install --save-dev babel-plugin-transform-runtime
你只需要配置.babelrc:
// .babelrc
{
"plugins": [
"transform-runtime"
]
}
7.babel-preset-env
相信没升级过babel-preset-env的,在安装babel-preset-es2015/es2016/es2017,会遇到下面的提示
babel-preset-env
babel-preset-env将基于你的实际浏览器及运行环境,自动的确定babel插件及polyfill,编译ES2015及此版本以上的语言,在没有配置项的情况下,babel-preset-env表现的同babel-preset-latest一样(或者可以说同babel-preset-es2015, babel-preset-es2016, and babel-preset-es2017结合到一起,表现的一致)。 babel-preset-env详细配置
npm install babel-preset-env --save-dev
(1)不用babel-preset-env
{
"presets": ["react", "es2015", "stage-1"],
"plugins": [
"transform-remove-strict-mode",
"transform-class-properties",
"transform-flow-strip-types",
]
}
(2)用babel-preset-env
你不在需要根据兼容的语法和API去引入对应的plugin,babel-preset-env会根据你对应的配置帮你自动引入依赖的插件
{
"presets": ["react", "env", "stage-1"]
}
8.webpack配置babel-present-env
webpack以配置兼容chrome 44 版本及以上,IE 9 及以上为例,配置如下:
- webpack.config.js文件
// webpack v3.x module配置
module: {
rules: [{
test: /\.html$/,
loader: 'html-loader?minimize=false'
}, {
test: /\.json$/,
loader: 'json-loader'
}, {
test: /\.(?:jpg|gif|png)$/,
loader: 'url-loader?limit=10240&name=../images/[name]-[hash:10].[ext]'
}, {
test: /\.js$|\.jsx$/,
exclude: /(node_modules|bower_components)/,
use: [{
loader: 'babel-loader'
}]
}]
}
- .babelrc文件
{ "presets": [ [ "env", { "targets": { "browsers": [ "last 2 versions", "chrome >= 44", "ie >= 9" ] } } ], "react", "stage-1" ] }