Rust Plugin Api
本文档仅涵盖插件钩子详情。 有关如何创建、构建和发布 rust 插件,请参阅:编写 Rust 插件
配置 Rust 插件
通过 plugins 选项添加 Rust 插件:
在字符串中配置 Rust 插件包名称(或路径),并在对象中配置其选项。
编写 Rust 插件
有关详细信息,请参阅编写 Rust 插件。
插件 Hook 概述
Farm 提供了很多 rollup 风格的 hook,这些 hook 分为 build 阶段和 generate 阶段:

所有插件挂钩都接受一个名为 CompilationContext 的参数。 所有共享的编译信息都存储在 context 中。
Hook 共有三种(与 Rollup 相同):
first:钩子串行执行,当钩子返回非空值时立即返回。 (null 在 JS 中表示 null 和 undefined,在 Rust 中表示 None)。serial: 钩子串行执行,每个钩子的结果将传递到下一个钩子,使用最后一个钩子的结果作为最终结果。parallel:钩子在线程池中并行执行,并且应该被 隔离。
有关完整的 Plugin Hooks 定义,请参阅Plugin Trait
name
- required:
true - default:
返回此插件的名称。 例子:
priority
- required:
false - default:
定义该插件的优先级,值越大,该插件越早执行。 当插件具有相同优先级时,它们将按照与plugins中注册的顺序相同的顺序执行。
默认情况下,所有自定义插件的优先级都是 100。有些内部插件的优先级是 99,比如 plugin-script、plugin-css,您可以覆盖默认优先级时内部插件的行为。 但是一些内部插件的优先级是101,比如plugin-resolve,plugin-html,如果你想覆盖默认行为,你应该设置一个更大的优先级。
config
- required:
false - hook type:
serial - default:
在编译开始之前在config钩子中修改配置。 Config 结构体的定义请参考Config。 例子:
请注意, Rust Plugin 的 config 钩子是在 JS Plugin 的 config 和 configResolved 钩子之后调用的。
plugin_cache_loaded
- required:
false - hook type:
serial - default:
扩展插件的持久缓存加载。
当启用 持久缓存 时,在命中缓存时可能会跳过 加载 和 转换 挂钩。 如果您的插件依赖于以前的编译结果(例如,基于现有模块加载虚拟模块),您可能需要实现此钩子来加载插件的缓存信息,以确保缓存按预期工作。
例子:
注意:
deserialize由farmfe_core导出,它可以帮助您反序列化Vec<u8>中的结构体或枚举。- 缓存的结构体或枚举必须是rkyv可序列化的,您可以使用
farmfe_core公开的#[cache_item]快速创建可缓存的结构体。
build_start
- required:
false - hook type:
parallel - default:
在第一次编译开始之前调用。 您可以使用此挂钩来初始化插件的任何初始状态。
build_start 仅在第一次编译时调用一次。 如果你想在HMR或Lazy Compilation中更新ModuleGraph时做一些事情,你应该使用update_modules钩子。
resolve
- required:
false - hook type:
first - default:
从 importer 解析自定义 source ,例如从 a.ts 解析 ./b :
那么解析参数将是:
默认解析器的解析结果为:
HookContext 用于在您可以递归挂钩时传递状态,例如,您的插件在 resolve hook 中调用 context.plugin_driver.resolve:
在上面的示例中,我们调用 context.plugin_driver.resolve 并将 caller 作为参数传递,然后我们应该添加一个类似 if caller.as_str() == "FarmPluginCss" 的保护以避免无限循环。
注意:
- 默认情况下,您的
resolve hook在Farm内部默认解析器之后执行,只有内部解析器无法解析的源才会传递给您的插件,这意味着如果您想覆盖默认解析器 ,您需要将插件的优先级设置为大于101。 - 通常
resolved_path是指向文件的真实绝对路径。 但是您仍然可以返回一个虚拟模块 id,例如virtual:my-module,但是对于虚拟模块,您需要实现load钩子来自定义如何加载虚拟模块。 在 Farm 中,resolved_path + query = module_id。 ResolveKind表示导入类型,示例值:ResolveKind::Require(由 commonjs require 导入)、ResolveKind::CssImport(由 css 的 import 语句导入)等。meta可以在插件和钩子之间共享,您可以从任何插件中的load、transform和parse钩子的参数中获取meta。
load
- required:
false - hook type:
first - default:
自定义如何从已解析的模块路径或模块 ID 加载模块。 例如加载一个虚拟模块:
在 load 钩子中加载模块时需要 module_type 和 content 。 source_map 是可选的,如果您在 load 钩子中进行转换(不推荐,我们建议在这种情况下使用 transform 钩子)或者从其他位置加载原始源地图,则可以返回源地图。
transform
- required:
false - hook type:
serial - default:
根据**模块内容和模块类型**进行转换。 将 sass 转换为 css 的示例:
编写 transform hook 的正常步骤:
- 添加基于
module_type或resolved_path或module_id的if保护 - 对
内容进行转换 3.返回转换后的content、source_map和module_type
对于 ignore_previous_source_map ,如果您处理了 param.source_map_chain 并折叠了 transform hook 中以前插件的 source map。 您应该将ignore_previous_source_map设置为 true 以确保 source map 正确。 否则,您应该始终将此选项设置为 false 并让 Farm 处理 source map 链。
transform 钩子是内容到内容。 有一个类似的钩子叫做 process_module , process_module 是ast to ast。 所以如果你想转换加载的内容字符串,你需要使用transform钩子,如果你想转换ast,你应该使用process_module钩子。
parse
- required:
false - hook type:
first - default:
将**转换后的模块内容**解析为ast。 Farm 原生支持 Js/Jsx/Ts/Tsx、css 和 html。 通常你不需要实现这个钩子,除非你想支持除了Js/Jsx/Ts/Tsx、css和html之外的新的module_type,在这种情况下使用ModuleMetaData::Custom。
process_module
- required:
false - hook type:
serial - default:
对解析结果进行变换,通常做**ast变换**。 例如,Farm 将 ts 转换成 js:
在上面的示例中,我们忽略非脚本模块,并且去掉 ts/tsx 模块的 ast 中类型信息。
analyze_deps
- required:
false - hook type:
serial - default:
分析模块的依赖关系。 例如,我们有 a.ts :
那么通常这个钩子应该将2个条目推送到params.deps:
param.deps 稍后将传递给 resolve 钩子。 您还可以根据需要添加与模块的 ast 不相关的新 deps,Farm 将 resolve 、 load 这些不相关的模块并将它们添加到模块图中。
finalize_modules
- required:
false - hook type:
serial - default:
在密封模块之前做任何你想做的事情。 请注意,您只能修改 param.module 。
build_end
- required:
false - hook type:
parallel - default:
当从config.input开始的所有依赖都被处理并且ModuleGraph被成功构建时调用,您可以通过context.module_graph在这里获得完整解析的ModuleGraph。
build_end 仅在第一次编译时调用一次。 如果你想在HMR或Lazy Compilation中更新ModuleGraph时做一些事情,你应该使用module_graph_updated钩子。
generate_start
- required:
false - hook type:
parallel - default:
在生成阶段开始之前调用。
optimize_module_graph
- required:
false - hook type:
serial - default:
您可以在此处对 module_graph 进行优化。 对于内部插件,Farm 在这个钩子中进行树摇动和缩小。
analyze_module_graph
- required:
false - hook type:
first - default:
分析module_graph的**动态导入,并根据动态导入**对模块进行分组,返回分组后的模块。
通常你不应该实现这个钩子,除非你想在 Farm 中实现一个全新的打包算法。
partial_bundling
- required:
false - hook type:
first - default:
基于 module_group_graph 和 module_graph 将 modules 打包到 Vec<ResourcePot> 。 ResourcePot 是 Farm 用于保存打包模块的结构,它将被生成到 generate_resources 钩子中的最终资源,您可以将 ResourcePot 视为其他工具的 Chunk。
注意:
- 该钩子会在
首次编译、HMR和