We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
自从接触ES2015开始,babel就一直在用,每个项目都在用。每次初始化项目后,.babelrc和@babel/core、@babel/cli、@babel/preset-env、@babel/transform-runtime等等信手拈来,但是每次想要区别core-js、@babel/poly-fill、@babel/runtime、@babel/plugin-transform-runtime、@babel/preset-env,却又含糊不清,索性来一次整理。
ES2015
babel
.babelrc
@babel/core
@babel/cli
@babel/preset-env
@babel/transform-runtime
core-js
@babel/poly-fill
@babel/runtime
@babel/plugin-transform-runtime
我们都知道,ES的每次标准公布,都会有许多新的特性,而这些特性无非分为两部分,一部分是新语法,如箭头函数、解构赋值、扩展运算符、for...in、for...of、class、async/await等,另一部分是API扩展,如Promise、Map、Set、Array.from、String.prototype.includes等。
新语法
箭头函数
解构赋值
扩展运算符
for...in
for...of
class
async/await
API扩展
Promise
Map
Set
Array.from
String.prototype.includes
在低版本的浏览器中要使用高版本的ES特性,就需要对其代码进行转换。对于新语法,需要通过语法转换,比如将箭头函数转化为普通函数,将赋值结构转换成单独取值,将扩展运算符转换成Object.assign等实现,而这就是babel的核心工作。对于新API,我们是可以通过JavaScript原有的语法去实现的,实现类似功能的库叫做polyfill。
ES特性
普通函数
赋值结构
单独取值
Object.assign
新API
JavaScript
polyfill
当然,也不是所有API都可以通过polyfill实现,比如Proxy。
Proxy
以模块化方式实现了ES6+的标准API,包括Promise、Symbol、Map、Set等,还有各种原型链上的扩展,如String.prototype.inclues、Array.prototype.find等。说白了就是polyfill,对于箭头函数、async/await等语法,自然是无能为力的。
Symbol
String.prototype.inclues
Array.prototype.find
我们可以通过引入直接使用:
// import 'core-js' // 引入所有 import 'core-js/features/array/find'; import 'core-js/features/promise'; [1, 2, 3].find((i) => i === 1); Promise.resolve(64).then((x) => console.log(64));
当然,这么做会直接污染全局环境,例如Promise会挂在到window上,find会挂在到Array.prototype上,也可以通过命名空间方式引入:
window
find
Array.prototype
import find from 'core-js-pure/features/array/from'; import Promise from 'core-js-pure/features/promise';
从源码中可以看到,@babel/polyfill就是简单地直接引用core-js和regenerator-runtime。因此,它会将扩展的API直接挂载到全局(window)和对应的原型(prototype)上,但是这样会导致一些问题:
@babel/polyfill
regenerator-runtime
使用方式很简单,写在入口文件开头:
import '@babel/polyfill';
regenerator-runtime,一个提供用于Generator和异步函数的运行时。
可以在一定程度上替换@babel/polyfill来使用,主要解决了两个问题:
避免产生多次的helper函数。
babel在对新语法转换过程当中,会借助一些helper函数来实现,比如class语法:
helper函数
// 输入: class Circle {} // 输出: function _classCallCheck(instance, Constructor) { //... } var Circle = function Circle() { _classCallCheck(this, Circle); };
这里的_classCallCheck每次转换class语法都会产生,数量多起来极大影响最终的代码体积。为了解决这个问题,有个@babel/runtime专门封装了这些helper函数。通过@babel/plugin-transform-runtime将这些helper函数的引用替换为从@babel/runtime中引入。
_classCallCheck
解决@babel/polyfill中污染全局环境和体积过大的问题。
@babel/plugin-transform-runtime中维护了一份API和core-js特性模块间的映射,可以根据具体使用情况,按需自动引入这些core-js中的特性模块。
// 输入: const p = Promise.resolve() // 输出: var _promise = require("@babel/runtime-corejs2/core-js/promise"); var _promise2 = _interopRequireDefault(_promise); var p = _promise2.default.resolve();
但是,为了防止污染现有的运行环境,对于实例函数(如Array.prototype.find)并不支持。
在babel-runtime的6.x版本中,还集成了[email protected]/library(相当于core-js-pure),在7.x版本这部分被移除了,如果有需要,可以使用@babel/runtime-corejs2代替。
babel-runtime
6.x
[email protected]/library(相当于core-js-pure)
7.x
@babel/runtime-corejs2
在了解@babel/preset-ev先说说babel的编译过程以及plugin和preset的概念。
@babel/preset-ev
plugin
preset
babel-core作为的编译过程主要分为三个步骤:
babel-core
@babbel/parser
AST
@babel/generator
所以说,plugin中实现了具体的转换功能。比如要将箭头函数转化为普通函数,就需要@babel/plugin-transform-arrow-functions,要将class语法转化为函数实现,就需要@babel/plugin-transform-classes。
@babel/plugin-transform-arrow-functions
@babel/plugin-transform-classes
而preset则代表一组plugin。比如需要转换jsx的语法,只需要@babel/preset-react就行了,它已经包含了@babel/plugin-transform-react-jsx、@babel/plugin-transform-react-display-name、@babel/plugin-transform-react-jsx-source、@babel/plugin-transform-react-jsx-self。
jsx
@babel/preset-react
@babel/plugin-transform-react-jsx
@babel/plugin-transform-react-display-name
@babel/plugin-transform-react-jsx-source
@babel/plugin-transform-react-jsx-self
同理@babel/preset-env也代表了一组plugin。通过默认的配置,我们就能够使用ES最新规范中的语法,当然也可以通过配置来达到你需要的效果。
最后简单总结一下:
ES API
ES5+
ES5
The text was updated successfully, but these errors were encountered:
No branches or pull requests
自从接触
ES2015
开始,babel
就一直在用,每个项目都在用。每次初始化项目后,.babelrc
和@babel/core
、@babel/cli
、@babel/preset-env
、@babel/transform-runtime
等等信手拈来,但是每次想要区别core-js
、@babel/poly-fill
、@babel/runtime
、@babel/plugin-transform-runtime
、@babel/preset-env
,却又含糊不清,索性来一次整理。我们都知道,ES的每次标准公布,都会有许多新的特性,而这些特性无非分为两部分,一部分是
新语法
,如箭头函数
、解构赋值
、扩展运算符
、for...in
、for...of
、class
、async/await
等,另一部分是API扩展
,如Promise
、Map
、Set
、Array.from
、String.prototype.includes
等。在低版本的浏览器中要使用高版本的
ES特性
,就需要对其代码进行转换。对于新语法
,需要通过语法转换,比如将箭头函数
转化为普通函数
,将赋值结构
转换成单独取值
,将扩展运算符
转换成Object.assign
等实现,而这就是babel
的核心工作。对于新API
,我们是可以通过JavaScript
原有的语法去实现的,实现类似功能的库叫做polyfill
。core-js
以模块化方式实现了ES6+的标准API,包括
Promise
、Symbol
、Map
、Set
等,还有各种原型链上的扩展,如String.prototype.inclues
、Array.prototype.find
等。说白了就是polyfill
,对于箭头函数
、async/await
等语法,自然是无能为力的。我们可以通过引入直接使用:
当然,这么做会直接污染全局环境,例如
Promise
会挂在到window
上,find
会挂在到Array.prototype
上,也可以通过命名空间方式引入:@babel/polyfill
从源码中可以看到,
@babel/polyfill
就是简单地直接引用core-js
和regenerator-runtime
。因此,它会将扩展的API直接挂载到全局(window)和对应的原型(prototype)上,但是这样会导致一些问题:使用方式很简单,写在入口文件开头:
@babel/plugin-transform-runtime
可以在一定程度上替换
@babel/polyfill
来使用,主要解决了两个问题:避免产生多次的helper函数。
babel
在对新语法
转换过程当中,会借助一些helper函数
来实现,比如class
语法:这里的
_classCallCheck
每次转换class
语法都会产生,数量多起来极大影响最终的代码体积。为了解决这个问题,有个@babel/runtime
专门封装了这些helper函数
。通过@babel/plugin-transform-runtime
将这些helper函数
的引用替换为从@babel/runtime
中引入。解决
@babel/polyfill
中污染全局环境和体积过大的问题。@babel/plugin-transform-runtime
中维护了一份API和core-js特性模块间的映射,可以根据具体使用情况,按需自动引入这些core-js
中的特性模块。但是,为了防止污染现有的运行环境,对于实例函数(如
Array.prototype.find
)并不支持。@babel/preset-env
在了解
@babel/preset-ev
先说说babel
的编译过程以及plugin
和preset
的概念。babel-core
作为的编译过程主要分为三个步骤:@babbel/parser
将代码转换为AST
。babel
本身不具备代码编译转换功能,而是依赖于一个个plugin
来进行处理,转换过后的代码仍然是AST
。@babel/generator
将AST
转换为JS代码。所以说,
plugin
中实现了具体的转换功能。比如要将箭头函数
转化为普通函数,就需要@babel/plugin-transform-arrow-functions
,要将class
语法转化为函数实现,就需要@babel/plugin-transform-classes
。而
preset
则代表一组plugin
。比如需要转换jsx
的语法,只需要@babel/preset-react
就行了,它已经包含了@babel/plugin-transform-react-jsx
、@babel/plugin-transform-react-display-name
、@babel/plugin-transform-react-jsx-source
、@babel/plugin-transform-react-jsx-self
。同理
@babel/preset-env
也代表了一组plugin
。通过默认的配置,我们就能够使用ES最新规范中的语法,当然也可以通过配置来达到你需要的效果。总结
最后简单总结一下:
@babel/polyfill
为运行环境提供能完整的ES API
,但是体积较大,新的语法如环境不支持还是不支持。@babel/plugin-transform-runtime
能够按需自动引入ES API
,能够有效控制体积,但是不支持函数实例方法,不对语法进行转换。@babel/preset-env
集成若干plugin
,能将ES5+
语法转换成ES5
语法,不集成ES API
的polyfill。The text was updated successfully, but these errors were encountered: