@babel/register
另一个使用 Babel 的方法是通过 require 钩子(hook)。require 钩子
将自身绑定到 node 的 require
模块上,并在运行时进行即时编译。
这和 CoffeeScript 的
coffee-script/register 类似。
安装
- npm
- Yarn
- pnpm
npm install @babel/core @babel/register --save-dev
yarn add @babel/core @babel/register --dev
pnpm add @babel/core @babel/register --save-dev
用法
require("@babel/register");
node 后续运行时所需要 require 进来的扩展名为 .es6
、.es
、.jsx
、
.mjs
和 .js
的文件将由 Babel 自动转换。
当所需的功能需要使用 polyfill 来实现时, 你必须将它们逐个引入,例如 生成器(generators)。
默认忽略 node_modules
注意: 默认情况下,所有对 node_modules
目录下的文件的 require 请求都将被忽略。你可以
通过以下方式传递一个用于匹配被忽略文件的正则表达式来修改默认行为:
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: [],
});
指定参数
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,
});
你还可以传递所有其他 参数 ,包括 plugins
和 presets
。
注意,配置文件 也将被加载,并且
编程方式的配置也将被合并进来,放在这些配置项的顶部。@babel/register
在配置文件中不支持
ignore
和 only
参数。
环境变量
默认情况下,@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)。
Experimental Babel 8 implementation
You can also test the new experimental implementation that will be enabled by default in Babel 8, using
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 (usingrequire("@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 ababel.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 模块的加载。