跳到主要内容

@babel/register

另一个使用 Babel 的方法是通过 require 钩子(hook)。require 钩子 将自身绑定到 node 的 require 模块上,并在运行时进行即时编译。 这和 CoffeeScript 的 coffee-script/register 类似。

安装

npm install @babel/core @babel/register --save-dev

用法

JavaScript
require("@babel/register");

node 后续运行时所需要 require 进来的扩展名为 .es6.es.jsx.mjs.js 的文件将由 Babel 自动转换。

Polyfill 不会被引入进来

当所需的功能需要使用 polyfill 来实现时, 你必须将它们逐个引入,例如 生成器(generators)。

默认忽略 node_modules

注意: 默认情况下,所有对 node_modules 目录下的文件的 require 请求都将被忽略。你可以 通过以下方式传递一个用于匹配被忽略文件的正则表达式来修改默认行为:

JavaScript
require("@babel/register")({
// This will override `node_modules` ignoring - you can alternatively pass
// an array of strings to be explicitly matched or a regex / glob
ignore: [],
});

指定参数

JavaScript
require("@babel/register")({
// Array of ignore conditions, either a regex or a function. (Optional)
// File paths that match any condition are not compiled.
ignore: [
// When a file path matches this regex then it is **not** compiled
/regex/,

// The file's path is also passed to any ignore functions. It will
// **not** be compiled if `true` is returned.
function(filepath) {
return filepath !== "/path/to/es6-file.js";
},
],

// Array of accept conditions, either a regex or a function. (Optional)
// File paths that match all conditions are compiled.
only: [
// File paths that **don't** match this regex are not compiled
/my_es6_folder/,

// File paths that **do not** return true are not compiled
function(filepath) {
return filepath === "/path/to/es6-file.js";
},
],

// Setting this will remove the currently hooked extensions of `.es6`, `.es`, `.jsx`, `.mjs`
// and .js so you'll have to add them back if you want them to be used again.
extensions: [".es6", ".es", ".jsx", ".js", ".mjs"],

// Setting this to false will disable the cache.
cache: true,
});

你还可以传递所有其他 参数 ,包括 pluginspresets。 注意,配置文件 也将被加载,并且 编程方式的配置也将被合并进来,放在这些配置项的顶部。@babel/register 在配置文件中不支持 ignoreonly 参数。

环境变量

默认情况下,@babel/node 命令行工具 和 @babel/register 会将缓存以 json 文件的形式放到 临时目录下。

随着文件的启动和编译,这将大大的提升效率。 但是,在某些情况下你可能需要修改这种行为方式,你可以通过 修改某些环境变量来满足你的需求。

BABEL_CACHE_PATH

指定另一个用于缓存的位置。

Shell
BABEL_CACHE_PATH=/foo/my-cache.json babel-node script.js

BABEL_DISABLE_CACHE

关闭缓存。

Shell
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)。

Experimental Babel 8 implementation

You can also test the new experimental implementation that will be enabled by default in Babel 8, using

JavaScript
require("@babel/register/experimental-worker");

It internally runs Babel asynchronously, so it's compatible with .mjs configuration files. You can already use it as a replacement of @babel/register with a few caveats:

  • If you programmatically specify @babel/register options (using require("@babel/register")({ /* ... options */ })), you must make sure that they are serializable. This means that you cannot pass plugin functions defined inline, but you must move them to a separate ./my-plugin.js file or to a babel.config.js file.
  • The new implementation is still experimental: it should have the same features as the existing one, but there may be some new bugs and regressions.

注意: @babel/register 支持即时编译原生的 Node.js ES 模块,因为目前尚无稳定的 API 来拦截 ES 模块的加载。