来到第五部分,主要记录一下 babel-register 与 babel-core。

前情提要

最近发生了种种小事,但是无论怎样,我总是信奉着一句话:“别人看到的永远是表面”。然后我在长期健身中悟道的一句话也送给大家共勉。

The fucking harder you tried, the fucking stronger you will be.

好,言归正传。上一节《Babel 入门教程(四):babel-cli 与 babel-node 及工程实践》中我们讲到了 babel-clibabel-node 如何辅助我们转译 ES6 文件或者支持我们在终端的 REPL 上进行 ES6 的代码运行,比较轻松和简单。

那么有没有办法让我们在文件中直接写 ES6 代码,而且写完之后不用通过 babel-cli 来进行转译文件呢?有!就是今天所要讲的 babel-registerbabel-core

Babel 5.x 与 Babel 6.x

babel-registerbabel-core 之前一定要重新提及一下 babel 的版本。很多教程和很多同学在这里并没有一个很清晰的概念,导致会安装使用就行了,也不问为什么。

近几年 babel 有版本 5.x 和 6.x,那么两者有什么区别呢?

  • 5.x 对新手更加友好,因为只需要安装一个babel就可以了,而6需要安装比较多的东西和插件才可以;
  • 相比 5.x 来说,6.x 将命令行工具和 API 分开来了,最直观的感觉就是,当你想在代码中运行 ES6 代码的话,需要安装 babel-register,而如果你想在终端编译 ES6 或者是运行 ES6 版本的 REPL 的话,需要安装 babel-cli
  • 原先的 babel 的 package 到了 6.x 版本之后虽然还是能安装,但是已经不具有任何的有效的代码了。取而代之的是一段提示文字,提示你需要安装 babel-cli,所以你在 babel6 的情况下,完全不需要安装 babel 这个 npm 包;
  • 6.x 将 babel 插件化,当你第一次安装 babel-register 并且按照以前的方式来加载 require hook 的话,你会发现代码无法运行,因为要求需要 .babelrc 配置文件或者在 package.json 中添加相关的 babebl 的插件配置

图片

babel-register

github 上官方对其的描述:

The require hook will bind itself to node’s require and automatically compile files on the fly.

该 npm 包用于实时加载 ES6 语法写的脚本文件,但是由于实时加载解析为 ES5 语法代码有时间上的延迟,所以仅适用于开发环境。

babel-register 包改写 require 命令,为它加上一个钩子,就是在上面提到的 require hook。此后,每当使用 require 加载 .js.jsx.es.es6 后缀名的文件,就会先用 Babel 进行转码。

安装 babel-register:

1
$ npm i -D babel-register

使用:

1
2
3
4
5
require('babel-register');
// 也可以在加载该钩子的时候传入配置参数
// require('babel-register')(configObj);

require('./es6/example.js')

注意:可以在加载该钩子的时候传入默认配置,也可以在加载实例文件的时候传入特例配置;另外,.babelrc 还是对每一个文件的实时转译都起作用的。

详细的配置参数可以上 github 上查看。

https://github.com/babel/babel/packages/babel-register

babel-core

github 上官方对其的描述:

Babel compiler core.

这描述真的可以再短一点呢。

如果某些代码需要调用 Babel 的 API 进行转码,就要使用 babel-core 包。它是 Babel 的核心依赖包。

安装 babel-core:

1
$ npm i -S babel-core

注意:所有以下涉及到的 options 字段请查阅中文官网文档,链接如下。

https://babeljs.cn/docs/core-packages/

或者 github 上的官方仓库

https://github.com/babel/babel/packages/babel-core

使用 babel-core 之 babel-transform

该 API 语法:

1
2
3
4
5
/**
* @param String code
* @param Object options 可省略
*/
babel.transform(code, options) // => { code, map, ast }

该 API 作用:
将传入的 code 进行转换。返回值为一个对象,参数分别为生成的代码,source map 以及 AST 。

示例:

1
2
3
4
5
var result = babel.transform("code();", options);

result.code;
result.map;
result.ast;

使用 babel-core 之 babel-transformFile

该 API 语法:

1
2
3
4
5
6
7
8
/**
* @param String filename
* @param Object options 可省略
* @param Function callback 回调函数
*/
babel.transformFile(filename, options, function callback(result){
result; // => { code, map, ast }
})

该 API 作用:
异步转译文件中的全部内容。

使用 babel-core 之 babel-transformFileSync

该 API 语法:

1
2
3
4
5
6
/**
* @param String filename
* @param Object options 可省略
* @param Function callback 回调函数
*/
babel.transformFileSync(filename, options); // => { code, map, ast }

该 API 作用:
babel.transformFile 的同步版本。返回值为 filename 文件中转译后的代码。

示例:

1
babel.transformFileSync("./es6/filename.js", options).code;

使用 babel-core 之 babel.transformFromAst

该 API 语法:

1
2
3
4
5
6
/**
* @param Object ast
* @param String code
* @param Object options 可省略
*/
babel.transformFromAst(ast, code, options)

该 API 作用:
给定一个 AST ,将它进行转换。

babel-core/register

最后再提及一下 babel-core/register

相信大家可能在网上的教程中有看到是拿这个做 require hook 的。这个要被官方在 Babel 7.x 中废弃了,所以大家弃用吧,直接用 babel-register 就好。

实际上,就是把 babel-core/register 这个 npm 包拆解成 babel-corebabel-register 两个 npm 包了。

很良心地给大家贴上 stackoverflow 上的回答:

They are the same. All babel-core/register does is require(‘babel-register’). https://github.com/babel/babel/blob/cb8c4172ef740aa562f0873d602d800c55e80c6d/packages/babel-core/register.js#L3

The recommended usage is babel-register since that is the module where the code actually lives, and babel-core/register has been removed in Babel 7.x. Better to depend specifically on the module you use, rather than load it as a side-effect of babel-core.

然后大家可以到那个回答上贴出的链接上去看看,其实就是 babel-core 包下 register.js 文件的内容,我很良心地给大家贴出来:

1
2
3
/* eslint max-len: 0 */
// TODO: eventually deprecate this console.trace("use the `babel-register` package instead of `babel-core/register`");
module.exports = require("babel-register");

看到那句 TODO 开头的话了吧。

babel-core 与 babel-register 的关系

这个就更简单了。

还是 babel-core 包下 register.js 文件的内容:

1
2
3
/* eslint max-len: 0 */
// TODO: eventually deprecate this console.trace("use the `babel-register` package instead of `babel-core/register`");
module.exports = require("babel-register");

就这么短短几行,表明了 babel-core 依赖于 babel-register 来实现一些核心的 API 函数。

所以这么使用场景就很清楚了,需要实时转译 ES6 文件,就用 babel-register,简单单一。

需要使用更高级的功能,也就是需要在实时转译时对转译过程和结果要来把控的话,就用 babel-core,利用其 API 来实现。

最后别忘了,使用这两个 npm 包的时候,不能忘了安装和引入我们前几节所说的 babel-preset-*babel-plugin-* 插件呀!还有 .babelrc 配置文件是一切转译工作进行的前提呀!

结语

有没有感觉本叔写教程还是很清晰,也很良心全面的?!

如果你对本系列教程有好感的话,不妨转发分享给朋友或者票圈,又或者点个赞或者留句话。我想认识更多的读者呢,哈哈哈。

明天会发本系列教程的最后一篇了,谢谢大家这几天的支持。



微信公众号