# @babel/注册

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

# 安装 (opens new window)

  • npm
npm install @babel/core @babel/register --save-dev
  • yarn
yarn add @babel/core @babel/register --dev

# 用法 (opens new window)

require("@babel/register");

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

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

# 默认忽略 node_modules (opens new window)

注意: 默认情况下,所有对 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: [],
});

# 指定参数 (opens new window)

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。 注意,配置文件 (opens new window) 也将被加载,并且 编程方式的配置也将被合并进来,放在这些配置项的顶部。@babel/register在配置文件中不支持 ignoreonly参数。

# 环境变量 (opens new window)

默认情况下,@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)。

# 实验性 Babel 8实现

您还可以测试将在 Babel 8 中默认启用的新实验性实现,使用

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

它在内部异步运行 Babel,因此它与.mjs配置文件 (opens new window) 兼容。您已经可以使用它来替代@babel/register一些警告:

  • 如果您以编程方式指定* @babel/register选项(使用require("@babel/register")({ /* ... options */ })),则必须确保它们是可序列化的。这意味着你不能传递内联定义的插件函数,但你必须将它们移动到一个单独的./my-plugin.js文件或一个babel.config.js文件中。
  • 新的实现仍然是实验性的:它* 应该* 具有与现有的相同的特性,但可能会有一些新的错误和回归。

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

Last Updated: 6/7/2023, 9:06:23 AM