码迷,mamicode.com
首页 > 其他好文 > 详细

关于babel,你应该知道的一些事

时间:2019-10-02 23:18:27      阅读:346      评论:0      收藏:0      [点我收藏+]

标签:不同的   仓库   tab   接下来   -o   c函数   nts   error   经历   

概要

babel本身是一个工具,负责将es6/es7的代码转换成es5的代码,以便在现代浏览器里面运行,更重要的是,babel的扩展机制使其可以为React转换jsx,为Flow做静态语法分析。

babel由各种小模块组成,它通过预置一些插件来转换代码,我们接下来会谈到。

注意: 假设你本地安装了node和npm,且不排斥使用命令行工具,同时确保你的项目里面包含pajkage.json文件;

babel-cli

Babel CLI通过命令行实现代码的转换,你可以通过 npm install babel-cli -g 全局安装它,当然也可以在本地项目目录下执行 npm install babel-cli –save-dev 实现本地安装,

这里推荐项目本地安装的方式,主要有以下两个优势:

1.不同的项目本身对babel的版本依赖会有所差异,防止强依赖;
2.项目本身依赖的babel版本可以任意自由灵活管控;

项目安装完 babel-cli 依赖之后,你就可以在控制台输入以下指令:

1
babel example.js --out-file compiled.js

指令每部分的含义:

  • babel 调用babel cli;
  • example.js 指定的需要转换的es6/es7文件;
  • –out-file babel 编译选项,代表编译完的文件输出信息,可以简写成 -o,如果需要编译目录文件,则输出项用 –output-dir ,可以简写成 -d;
  • compiled.js - 指定输出的文件名;

每次改完代码都敲一遍指令,显然是件繁琐的事,我们可以通过给package.json的scripts配置一条构建任务指令,实现该步骤的自动化:

1
2
3
4
5
6
7
{
...
"scripts": {
"build": "babel ./src -d ./lib -w"
}
...
}

以上-w指令代表babel会监视src目录下的文件变化,如变化就执行重新编译该代码并输入到lib目录下;

babel-register

babel-register 通过绑定node的require函数,通过钩子函数实现在线代码转换;这种方式不推荐在生产环境使用,由于实时代码转换会带来性能的损耗而导致体验低下,所以更优的方式是代码部署前先完成代码的转换;

不过开发环境使用还是很方便的,可以实现直接编译并执行代码,那如何使用babel-register呢?
首先需要通过以下指令安装 babel-register

1
npm install babel-register --save-dev

创建一个简单es6/es7文件 index.js:

1
2
const sayHello = () => {console.log('hello')};
sayHello();

创建新文件去require index.js文件 register.js:

1
2
require('babel-register');
require('index.js');

当我们运行 node register.js时,控制台会输出 hello;

babel-node

如果想快速的执行一个需babel转换的文件,最好的方式是使用 babel-node 命令, 该方式同样不建议在生产环境使用,理由同上,安装了babel cli天然就携带了babel-node,如何使用呢?

首先 创建一个简单es6/es7文件 index.js:

1
2
const sayHello = () => {console.log('hello')};
sayHello();

接下来直接 babel-node index.js ,接下来就可以在控制台看到 hello 的输出;

Configuring Babel

正如之前所说,如果你不告知babel该做什么,babel本事不会做任何事情,除了将文件从一个地方挪到另一个地方,所以我们必须给babel提供presets和plugins配置来告知babel如何工作。

.babelrc

.babelrc 文件是babel的配置文件,大概的文件结构如下

1
2
3
4
{
"presets": [],
"plugins": []
}

现在假设我们要通过babel的配置文件告知babel将一份基于标准 es6 React的代码转成es5,如何做?

  1. 首先我们需要安装es2015的preset和React的preset;
1
2
npm install babel-preset-es2015 --save-dev
npm install babel-preset-react --save-dev
  1. 更新 .babelrc , 添加preset配置即可;
1
2
3
4
{
"presets": ["es2015", "react"],
"plugins": []
}

那如果我们的代码文件里面用了许多es6草案阶段(Draft)的语法时,babel需要额外添加什么preset呢,众所周知,一个标准的js规范需要经历5个阶段(Strawman, Proposal, Draft, Candidate, Finished),才会最终纳入标准,而草案阶段是很有可能最终纳入标准的, babel通过预置不同阶段的preset完成相应转换工作,主要有以下4个:

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

之所以没有 babel-preset-stage-5 , 是因为它就是 babel-preset-es2015

以上每个stage的preset都依赖它后一个preset,例如babel-preset-stage-1依赖于 babel-preset-stage-2 和 babel-preset-stage-3

所以要支持草案阶段的语法只要先安装对应的preset,

1
npm install babel-preset-stage-2

然后更改babel配置文件即可:

1
2
3
4
{
"presets": ["es2015", "react", "stage-2"],
"plugins": []
}

babel-polyfill

babel-polyfill 会模拟整个es6环境,例如在没有polyfill的情况下,以下代码:

1
2
3
function () {
return Array.from(arguments).map((a) => a + 2);
}

会转换成

1
2
3
4
5
function () {
return Array.from(argument).map(function (a) {
return a + 2;
});
}

这段代码其实在很多浏览器(低版本的qq浏览器,百度浏览器等)下并不能正常工作,由于它们的js内核并不支持Array.from api:

1
Uncaught TypeError: Array.from is not a function

为了解决这个问题,我们需要添加一个polyfill, 一个polyfill本身就是一个代码片段,它实现了当前js运行环境未实现的本地api,babel采用corejs作为它的polyfill,采用 regenerator支持generators和async函数;

要支持babel polyfill功能,首先需要安装它:

1
npm install babel-polyfill --save-dev

然后在任何需要用到polyfill的文件的顶部引用该文件:

1
import 'babel-polyfill';

babel高级配置

很多人只是用babel 内置些 presets去完成一些工作,但其实babel的能力远不仅如此:

手工配置插件

babel的presets本身就是一系列预置的插件,如果你想添加一些特殊的支持,你可以手工添加额外的插件,例如你想让你的代码支持es7 的decorators,你只要先安装对应的decorators插件:

1
npm install babel-plugin-transform-decorators --save-dev

然后添加到.babelrc文件中即可:

1
2
3
4
{
"presets": ["es2015"],
"plugins": ["transform-decorators"]
}

你可以在babel官网查看babel 官方插件列表,你也可以在npm仓库查看开源社区贡献的babel插件列表

有些插件还可以额外添加一些配置项,例如很多插件会包含一个 “loose” 配置项用来指定 丢弃一些标准规范的行为,以便生成更简单,更健壮的代码;

1
2
3
4
5
{
...
plugins: ["transform-es2015-classes", { "loose": true }]
...
}

分环境配置babel

babel有很多插件提供了对开发过程中的支持,同时也有很多插件提供了对生产环境的代码优化,你可以通过指定不同环境动态加载不同的babel插件:

1
2
3
4
5
6
7
8
9
10
11
{
"presets": ["es2015"],
"env": {
"development": {
"plugins": [...]
},
"production": {
"plugins": [...]
}
}
}

当前的上下文环境是根据 process.env.BABEL_ENV 获取的,若没有,则尝试从 process.env.NODE_ENV 获取,若NODE_ENV也没有,则默认是 development 环境;

以下是分别在Unix和Windows系统上设置环境变量的方式:

Unix:

1
2
$ BABEL_ENV=development
$ NODE_ENV=development

Windows:

1
2
$ SET BABEL_ENV=development
$ SET NODE_ENV=development

当然更好的方式是使用类似cross-env的npm 包,它可以让你通过脚本参数指定环境变量。

构建自己的babel配置

每次写相同的babel配置文件其实很浪费时间,所以我们需要构建自己的presets模块

假设有如下的 .babelrc

1
2
3
4
{
"presets": ["es2015", "react"],
"plugins": ["transform-decorators"]
}

接下来你要做的就是命名该项目 babel-preset-* ,然后创建两个文件:
一个 package.json 文件:

1
2
3
4
5
6
7
8
9
10
{
"name": "babel-preset-awesome",
"version": "1.0.0",
"author": "Kliment Petrov <kleopetroff@gmail.com> (http://kleopetrov.me)",
"dependencies": {
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-plugin-transform-decorators": "^6.6.5",
}
}

然后,创建一个 index.js 文件并导出 .babelrc 的上下文,将文件中的preset和插件改为用require的方式调用:

1
2
3
4
5
6
7
8
9
10
11
module.exports {
{
presets: [
require("es2015"),
require("react")
],
plugins: [
require("transform-decorators")
]
}
}

最后将它发布到npm仓库即可;

其它工具

babel也可以和其它工具例如 linting,代码风格 配合一起使用

Linting

最有名的Linting工具非eslint莫属,babel将其整合到官方支持,首先,我们需要安装对应的包:

1
npm install eslint babel-eslint --save-dev

接下来,在你的项目下创建 .eslintrc 文件,并做配置:

1
2
3
4
5
6
{
"parser": "babel-eslint",
"rules": {
...
}
}

最后在你的package.json配置lint脚本,然后执行npm run lint即可:

1
2
3
4
5
6
7
{
...
"scripts": {
"lint": "eslint ./src/*.js*"
}
...
}

编辑器插件

由于babel使用者越来越多,各大ide也提供了相应的babel插件支持

总结

babel和其周边的生态在当今web开发中扮演越来越重要的角色,通过这篇文章的介绍,你可以通过配置尽情的使用最新的js规范及周边技术(JSX, Flow, 等等),话不多说,赶快开始吧!

原文:大专栏  关于babel,你应该知道的一些事


关于babel,你应该知道的一些事

标签:不同的   仓库   tab   接下来   -o   c函数   nts   error   经历   

原文地址:https://www.cnblogs.com/wangziqiang123/p/11618430.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!