本节我们来讲一下 @babel/register。使用 Babel 的方法之一就是通过 require 钩子(hook),require 钩子将自身绑定到 node 的 require 模块上,并在运行时自动编译文件。这和 CoffeeScript 的 coffee-script/register 类似。
安装
@babel/register 只有一个功能,就是重写 node 的 require 方法。
安装命令如下所示:
npm install @babel/core @babel/register --save-dev
安装好后可以通过 require 引用,如下所示:
require("@babel/register");
@babel/register 在底层改写了 node 的 require 方法,在代码里引入 @babel/register 模块后,所有通过require引入并且以 .es6,.es,.jsx, .mjs,和 .js 为后缀名的模块都会被 Babel 转译。
默认忽略node_modules
默认情况下,所有对 node_modules 目录下的文件的 require 请求都将被忽略。我们可以通过以下方式传递一个用于匹配被忽略文件的正则表达式来修改默认行为:
require("@babel/register")({
ignore: [],
});
指定参数
require("@babel/register")({
ignore: [
/regex/,
function(filepath) {
return filepath !== "/path/to/es6-file.js";
},
],
only: [
/my_es6_folder/,
function(filepath) {
return filepath === "/path/to/es6-file.js";
}
],
extensions: [".es6", ".es", ".jsx", ".js", ".mjs"],
cache: true,
});
或者还可以传递其他的参数,例如 plugins 和 presets。需要注意的是,配置文件也将被加载,并且编程方式的配置也将被合并进来,放在这些配置项的顶部。
环境变量
默认情况下,@babel/node 命令行工具和 @babel/register 会将缓存以 json 文件的形式放到临时目录下。
随着文件的启动和编译,这将大大的提升效率。 但是在某些情况下我们可能需要修改这种行为方式,可以通过修改某些环境变量来满足需求。
BABEL_CACHE_PATH
指定另一个用于缓存的位置:
BABEL_CACHE_PATH=/foo/my-cache.json babel-node script.js
BABEL_DISABLE_CACHE
关闭缓存:
BABEL_DISABLE_CACHE=1 babel-node script.js
即时编译插件和preset
@babel/register 使用 Node 的 require() 钩子系统(hook system)在加载文件时即时编译文件。虽然这在总体上很有帮助,但这意味着 require() 钩子中的代码会导致更多的 require 调用,从而导致依赖循环的情况出现。
以 Babel 为例,这可能意味着在 Babel 试图编译用户的文件的过程中,Babel 最终可能会在加载自己时尝试编译自己。
为了避免这个问题,这个模块明确的禁止重新进入编译,例如 Babel 自己的编译逻辑明确禁止触发进一步编译任何其他正在运行的文件。
这样做的缺点是如果我们想定义一个插件或 preset,并且这个插件或 preset 本身是实时编译的,这个过程将会很复杂。
上述问题的关键在于我们自己的代码首先需要加载插件或 preset,假定插件或 preset 预先加载了其自身的所有依赖项,可以像下面这样做:
require("@babel/register")({
// ...
});
require("./my-plugin");
因为是由我们自己代码触发的加载,而不是 @babel/register 自身的业务逻辑,这样才能成功编译任何同步加载的插件或 preset。