.scss 或 .yaml。在 Bun 打包器的上下文中,插件可以用来实现框架级功能,如 CSS 提取、宏和客户端-服务端代码共存。
生命周期钩子
插件可以注册在打包生命周期各个阶段运行的回调:onStart(): 在打包器启动打包时运行一次onResolve(): 在模块解析之前运行onLoad(): 在模块加载之前运行onBeforeParse(): 在解析器线程中运行零拷贝原生插件,在文件解析之前运行
参考
插件类型的粗略概述(请参考 Bun 的bun.d.ts 以获取完整的类型定义):
用法
插件被定义为一个简单的 JavaScript 对象,包含一个name 属性和一个 setup 函数。
Bun.build 时传递给 plugins 数组。
插件生命周期
命名空间
onLoad 和 onResolve 接受一个可选的 namespace 字符串。什么是命名空间?
每个模块都有一个命名空间。命名空间用于在转译代码中为导入添加前缀;例如,一个具有 filter: /\.yaml$/ 和 namespace: "yaml:" 的加载器会将来自 ./myfile.yaml 的导入转换为 yaml:./myfile.yaml。
默认命名空间是 "file",不需要指定它,例如:import myModule from "./my-module.ts" 与 import myModule from "file:./my-module.ts" 相同。
其他常见命名空间有:
"bun": 用于 Bun 特定模块(例如"bun:test"、"bun:sqlite")"node": 用于 Node.js 模块(例如"node:fs"、"node:path")
onStart
Promise。在打包过程初始化后,打包器会等待所有 onStart() 回调完成后再继续。
例如:
onStart()(休眠 10 秒)完成,以及第二个 onStart()(将打包时间写入文件)完成。
注意 onStart() 回调(像其他每个生命周期回调一样)无法修改 build.config 对象。如果你想修改 build.config,必须直接在 setup() 函数中进行。
onResolve
onResolve() 插件生命周期回调允许你配置模块是如何被解析的。
onResolve() 的第一个参数是一个对象,包含 filter 和 namespace 属性。过滤器是对导入字符串运行的正则表达式。实际上,这些允许你过滤你的自定义解析逻辑将应用于哪些模块。
onResolve() 的第二个参数是一个回调函数,对于 Bun 找到的每个匹配第一个参数中定义的 filter 和 namespace 的模块导入,都会运行此回调。
回调接收匹配模块的_路径_作为输入。回调可以为模块返回一个新的_路径_。Bun 将读取_新路径_的内容并将其解析为模块。
例如,将所有导入到 images/ 的重定向到 ./public/images/:
onLoad
onLoad() 插件生命周期回调允许你在模块被 Bun 读取和解析之前修改模块的_内容_。
与 onResolve() 类似,onLoad() 的第一个参数允许你过滤这次 onLoad() 调用将应用于哪些模块。
onLoad() 的第二个参数是一个回调函数,对于每个匹配的模块,在 Bun 将模块内容加载到内存_之前_运行此回调。
这个回调接收匹配模块的_路径_作为输入,模块的_导入者_(导入该模块的模块)、模块的_命名空间_和模块的_种类_。
回调可以为模块返回一个新的 contents 字符串以及一个新的 loader。
例如:
import env from "env" 的导入转换为导出当前环境变量的 JavaScript 模块。
.defer()
传递给 onLoad 回调的一个参数是 defer 函数。这个函数返回一个 Promise,当所有_其他_模块都已加载时该 Promise 会被解决。
这允许你延迟执行 onLoad 回调,直到所有其他模块都已加载。
这对于返回依赖于其他模块的模块内容很有用。
示例:跟踪和报告未使用的导出
.defer() 函数目前有一个限制,即每个 onLoad 回调只能调用一次。
原生插件
Bun 的打包器如此快速的原因之一是它用原生代码编写,并利用多线程并行加载和解析模块。 然而,用 JavaScript 编写的插件的一个限制是 JavaScript 本身是单线程的。 原生插件是作为 NAPI 模块编写的,可以在多个线程上运行。这允许原生插件比 JavaScript 插件运行得更快。 此外,原生插件可以跳过不必要的工作,如将字符串传递给 JavaScript 所需的 UTF-8 -> UTF-16 转换。 以下是原生插件可用的生命周期钩子:onBeforeParse(): 在 Bun 的打包器解析文件之前在任何线程上调用。
在 Rust 中创建原生插件
原生插件是公开生命周期钩子作为 C ABI 函数的 NAPI 模块。 要创建原生插件,你必须导出一个匹配你想要实现的原生生命周期钩子签名的 C ABI 函数。terminal
terminal
lib.rs 文件中,我们将使用 bun_native_plugin::bun proc 宏来定义一个
将实现我们的原生插件的函数。
这是一个实现 onBeforeParse 钩子的例子: