babel

babel 编译的阶段

babel 总共分为三个阶段:解析,转换,生成。

我们需要知道现在 babel 本身是不具备这种转化功能,提供这些转化功能的是一个个 plugin。所以我们没有配置任何 plugin 的时候,经过 Babel 输出的代码是没有改变的。

Plugin —— transform 的载体

Babel 自 6.0 起,就不再对代码进行转换。现在只负责图中的 parse 和 generate 流程,转换代码的 transform 过程全都交给插件去做。

 

@babel/preset-env(按需加载)

Preset 是什么? Preset 插件套餐,每个套餐里打包了不同的插件,这样安装套餐就等于一次性安装各类 babel 插件。

首先在项目下安装:

$ npm install --save-dev @babel/preset-env

然后修改 .babelrc:

{
  "presets": ["@babel/preset-env"]

}

 

plugins 与 presets 同时存在的执行顺序

  1. 先执行 plugins 的配置项,再执行 Preset 的配置项;

  2. plugins 配置项,按照声明顺序执行;

  3. Preset 配置项,按照声明逆序执行。

列入以下代码的执行顺序为:

  1. transform-es2015-template-literals

  2. stage-2

  3. env

// .babelrc 文件
{
    
"plugins"
: [
        
"transform-es2015-template-literals"
,  
// 转译模版字符串的 plugins
    ],
    
"presets"
: [
        [
"env"
, {
            
// 是否自动引入 polyfill,开启此选项必须保证已经安装了 babel-polyfill
            
// “usage” | “entry” | false, defaults to false.
            
"useBuiltIns"
: 
"usage"
        }], 
"stage-2"
]
}

  

 useBuiltIns 配置

我们可能在全局引入 babel-polyfill,这样打包后的整个文件体积必然是会变大的。

但是通过设置 "useBuiltIns":"usage" 能够把 babel-polyfill 中你需要用到的部分提取出来,不需要的去除。

useBuiltIns 参数说明:

  1. false: 不对 polyfills 做任何操作

  2. entry: 根据 target 中浏览器版本的支持,将 polyfills 拆分引入,仅引入有浏览器不支持的 polyfill

  3. usage(新):检测代码中 ES6/7/8 等的使用情况,仅仅加载代码中用到的 polyfills

 

@babel/polyfill(完整模拟es2015+,体积庞大)

babel 编译过程处理第一种情况 - 统一语法的形态,通常是高版本语法编译成低版本的,比如 ES6 语法编译成 ES5 或 ES3。而 babel-polyfill 处理第二种情况 - 让目标浏览器支持所有特性,不管它是全局的,还是原型的,或是其它.

安装 babel-polyfill

$ npm install --save @babel/polyfill

使用 babel-polyfill

我们需要在程序入口文件的顶部引用 @babel-polyfill

require('@babel/polyfill')
[].findIndex('babel')

或者使用 ES6 的写法:

import '@babel/polyfill'
[].findIndex('babel')

需要注意的是,babel-polyfill 不能多次引用。如果我们的代码中有多个 require('@babel/polyfill'),则执行时会报告错误;

 

@babel/plugin-transform-runtime(按需引入,打包体积小,不能兼容实例方法)

我们首先安装插件:(@babel/plugin-transform-runtime需要依赖@babel/runtime)

$ npm install --save-dev @babel/plugin-transform-runtime

然后再安装 babel-runtime:

$ npm install @babel/runtime

最后在 .babelrc 中配置:

{
"plugins": [
"@babel/plugin-transform-object-assign", //如果我们要使用object.assign()对于
@babel/plugin-transform-runtime这样配置,而babel-polyfill引入即可

"@babel/plugin-transform-runtime"
]
}

这样,我们不需要 babel-polyfill 也一样可以在程序中使用 Object.assign,编译后的代码最终能够正常运行在 IE 11 下。

提问:在经过 @babel/plugin-transform-runtime 的处理后,IE 11 下现在有 Object.assign吗?

答案是,仍然没有。

这正是 babel-polyfill 与 babel-runtime 的一大区别,前者改造目标浏览器,让你的浏览器拥有本来不支持的特性;后者改造你的代码,让你的代码能在所有目标浏览器上运行,但不改造浏览器。

posted @ 2019-08-05 10:55  黄小鑫Celine  阅读(504)  评论(0编辑  收藏  举报