Skip to content
New issue

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

Babel相关配置备忘 #14

Open
waltcow opened this issue Mar 5, 2017 · 0 comments
Open

Babel相关配置备忘 #14

waltcow opened this issue Mar 5, 2017 · 0 comments

Comments

@waltcow
Copy link
Owner

waltcow commented Mar 5, 2017

Babel介绍

Babel 把用最新标准编写的 JavaScript 代码(ES6, ES7)向下编译成可以在今天随处可用的版本(ES3,ES5)。 这一过程叫做“源码到源码”编译, 也被称为转换编译。并且还可以支持React的JSX写法。

15 年 11 月,Babel 发布了 6.0 版本。相较于前一代 Babel 5,新一代 Babel 更加模块化, 将所有的转码功能以插件的形式分离出去,默认只提供 babel-core。原本只需要装一个 babel ,现在必须按照自己的需求配置,无需下载大量无用的依赖

在命令行中使用 Babel

因为 Babel 的不同版本以及不同转码规则会起到不同的效果,全局安装会带来不必要的麻烦。在命令提示符中转到自己的项目目录下:

$ npm install --global babel-cli
# or
$ npm install --save-dev babel-core
  • 如果你只想在命令行中使用babel 只需安装 babel-cli
  • 如果是要在Node上以编程的方式来使用 Babel ,则需要安装 babel-core

babel-core 的作用是把 js 代码分析成 ast ,方便各个插件分析语法进行相应的处理。有些新语法在低版本 js 中是不存在的,如箭头函数,rest 参数,函数默认值等,这种语言层面的不兼容只能通过将代码转为 ast,分析其语法后再转为低版本 js。首先安装 babel-core

如果你之前执行了全局安装,可以通过下面的代码卸载全局范围的 Babel。放心,这并不会影响到项目路径下的本地安装。

npm uninstall --global babel-cli

添加相关的plugin和preset

因为在babel6中没有默认的转换规则,当你没加任何配置去转换一个文件时,babel 只会把文件直接原码输出,不做任何的改变

如果你想转义一些相关的新特性,例如 arrow function
你需要先安装arrow function的相关plugin

npm install --save-dev babel-plugin-transform-es2015-arrow-functions

然后修改本地的.babelrc文件,加入以下的配置

{
  "plugins": ["transform-es2015-arrow-functions"]
}
// before
var foo = () => { 
  console.log('foo')
}

//after

'use strict';

var foo = function foo() {
  console.log('foo');
};

babel的plugin是往下兼容的,比如在ES2015中常量是 let,如果你想在ES5中运作则需额外的添加plugin编译

$ npm install --save-dev babel-plugin-check-es2015-constants
$ npm install --save-dev babel-plugin-transform-es2015-block-scoping
{
  "plugins": [
    "check-es2015-constants",
    "transform-es2015-block-scoping"
  ]
}

由于这些的依赖很难去记住,如果你不想刻意去定制,你只要配一下preset(就是一堆插件的集合)
preset类似于餐厅的套餐。如 babel-preset-es2015 打包了 es2015 的特性,babel-preset-stage-0 打包处于Strawman 初稿 阶段的语法,babel-preset-react包含了React的转码规则

babel-preset-stage-x的意义

以下是babel在4 个不同阶段的预设:

  • babel-preset-stage-0
  • babel-preset-stage-1
  • babel-preset-stage-2
  • babel-preset-stage-3

注意 stage-4 预设是不存在的因为它就是上面的 es2015 预设。

JavaScript 还有一些提案,正在积极通过 TC39(ECMAScript 标准背后的技术委员会)的流程成为标准的一部分。
这个流程分为 5(0-4)个阶段。 随着提案得到越多的关注就越有可能被标准采纳,于是他们就继续通过各个阶段,最终在阶段 4 被标准正式采纳。

  • 阶段 0: Strawman 初稿

一个推进 ECMAScript 发展的自由形式的想法。该想法必须由 TC39 的会员提交,如果是非会员则必须注册成为 TC39 贡献者才能提交。

  • 阶段 1:Proposal 建议

必须确定一位带头人来为负责这份建议。无论是带头人或者联合带头人都必须是 TC39 的会员(原文)。建议要解决的问题必须以简明的文字描述,而解决方案则要给出相应的实例和 API,并详细描述语义及算法。最后,必须指明此建议的潜在问题,例如与其他特性之间的关联,实现难点等。

  • 阶段 2:Draft 草案

草案是规范的第一个版本。其与最终标准中包含的特性不会有太大差别。建议此时必须要附加该特性的语法和语义的正式说明(使用 ECMAScript 标准的形式语言)。说明应该尽可能完善,但可以包含待办事项和占位符。该特性需要两个实验性的实现,其中一个可以在类似 Babel 的转译器(transpiler)中实现。

  • 阶段 3:Candidate 候选

候选阶段,建议基本完成,此时将从实现过程和用户使用两方面获取反馈来进一步完善建议。必备条件:规范文档必须是完整的。指定的评审人(由 TC39 而不是带头人指定)和 ECMAScript 规范的编辑须在规范上签字。还有至少要两个符合规范的实现(不必指定默认实现)。

  • 阶段 4:Finished 完成

建议已经准备就绪,可以添加到标准之中。

运行Babel 生成的代码

Babel 默认只转码 ES6 的新语法(syntax),而不转换新的API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign、Array.from)都不会转码。如果想让这写方法运行, babel 社区提供两种方案可以选择

  • babel-polyfill
  • babel-runtime + babel-plugin-transform-runtime

两个方案功能几乎相同,就是转码新增 API ,模拟 ES6 环境,但实现方法完全不同

babel-polyfill 的做法是将全局对象通通污染一遍,比如想在 node 0.10 上用 Promise,调用 babel-polyfill 就会往 global 对象挂上Promise 对象。对于普通的业务代码没有关系,但如果用在模块上就有问题了,会把模块使用者的环境污染掉。

babel-runtime 的作用也是模拟 ES2015 环境。只不过,babel-polyfill 是针对全局环境的,引入它,我们的浏览器就好像具备了规范里定义的完整的特性 – 虽然原生并未实现。babel-runtime 更像是分散的 polyfill 模块,我们可以在自己的模块里单独引入,比如 require(‘babel-runtime/core-js/promise’) ,它们不会在全局环境添加未实现的方法,只是,这样手动引用每个 polyfill 会非常低效。我们借助 Runtime transform 插件来自动化处理这一切。

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

// babelrc文件
 {
    "plugins": [
     "transform-runtime",
      "transform-es2015-classes"
    ]
  }
现在,Babel 会把这样的代码:

class Foo {
  method() {}
}

编译成:

import _classCallCheck from "babel-runtime/helpers/classCallCheck";
import _createClass from "babel-runtime/helpers/createClass";

let Foo = function () {
  function Foo() {
    _classCallCheck(this, Foo);
  }

  _createClass(Foo, [{
    key: "method",
    value: function method() {}
  }]);

  return Foo;
}();
@waltcow waltcow changed the title babel相关配置备忘 Babel相关配置备忘 Mar 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant