Skip to content

Latest commit

 

History

History
148 lines (126 loc) · 5.8 KB

2017-09-21-深入理解babel.md

File metadata and controls

148 lines (126 loc) · 5.8 KB
title date status
深入理解babel
2017-09-21
finished

babel

基于最新的ECMAScript将JS编译成在各个平台、各种版本的浏览器上都能运行的代码。它是js编译器。

babel从V6.0开始使用模块化,将所有功能以插件形式分离出来,默认只提供babel-core。使用更加灵活

使用babel

babel-cli

以命令行的方式用babel编译js

babel-core

以编程的形式用babel编译js

配置babel

简单的运行babel,只是输出了原样js,并没有按照预期的编译js。此时需要安装并配置插件(plugins)或预设(presets)来告诉babel如何编译。

插件(plugins):是单一的功能,例如,es2015-arrow-functionses2015-classes
预设(presets):是一组插件。

配置一般有两种方式:

  1. package.json 中的babel属性
  2. .babelrc文件

.babelrc

项目根目录创建.babelrc,一般有以下配置项:

{
    "presets": [],
    "plugins": [],
}

常用presets

babel-preset-es2015

打包了一系列es6特性的插件。当然还有babel-preset-2016,babel-preset-2017。

{
    "presets": [
        "es2015"
    ],
    "plugins": [],
}

babel-preset-env

为了让babel插件编译比较精简,这个预设可以声明编译环境,把js编译到满足声明的环境即可。配置官方文档说明: http://babeljs.io/docs/plugins/preset-env/

{
    "presets": [
        "env", {
            "target": {
                "node": "6.10",
                "browsers": "> 5%",
                "chrome": 56
            }
        }
    ],
}

babel-preset-stage-x

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函数抽离成模块

babel-polyfill

http://babeljs.io/docs/usage/polyfill/
polyfill: 代码填充或兼容性补丁。
在js全局补充还不存在的API功能函数,这样会覆盖运行环境提供的函数,造成全局污染。 它主要包括两个方面:

  1. regenerator runtime 可以在js总用generators、async functions
  2. core-js

⚠️ 它和babel-runtime一样可以配合plugins、presets一起使用。

使用
  1. npm install --save babel-polyfill
  2. 在node、webpack、browserify环境下引入:require("babel-polyfill");
  3. 在browser环境下:直接引入资源。
  4. 在一些环境下,可以直接引用用到的polyfill

babel-runtime

它和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功能函数)

transform-runtime技术要点

http://babeljs.io/docs/plugins/transform-runtime/#technical-details

  1. 当使用generators/async functions,自动依赖babel-runtime/regenerator
  2. 自动依赖babel-runtime/core-js并匹配ES6静态方法和内置方法。
  3. babel-runtime/helpers模块替换babel行内的helpers。(增加helpers函数的复用)。

具体实现包括

  • regenerator 重命名
  • corejs函数重命名
  • helper重命名

.babelrc 配置项说明

options的loose模式

宽松模式,很多转换器都有“宽松”模式,通过放弃一些标准中的行为来生成更简化且性能更好的代码。

{
    "plugins": [
        "transform-runtime",
        ["transform-es2015-classes", { "loose": true }]
    ]
}

plugins/presets排序

http://babeljs.io/docs/plugins/#plugin-preset-ordering

  • Plugins优先于Presets
  • Plugin是从左至右执行
  • Presets是从又至左执行
    • 这是为了向后兼容,因为很多用户的编写方式是["stage-0","es2015" ]

自定义plugins/presets

请参考官方文档:http://babeljs.io/docs/plugins/#plugin-development

⚠️ 本文参考文档 http://babeljs.io
https://segmentfault.com/a/1190000008159877
https://github.com/thejameskyle/babel-handbook/blob/master/translations/zh-Hans/user-handbook.md