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
和