插件 API
Nasti 兼容 Vite / Rollup 的核心模块钩子,并提供 Environment Driver API 接入 Rspeedy 等外部工具链。
基本结构
import type { NastiPlugin } from '@nasti-toolchain/nasti' function myPlugin(options = {}): NastiPlugin { return { name: 'my-plugin', // 必需,唯一标识 enforce: 'pre', // 可选: 'pre' | 'post' apply: 'build', // 可选: 'build' | 'serve' resolveId(source, importer) { // 解析模块标识符 }, load(id) { // 加载模块源代码 }, transform(code, id) { // 转换模块代码 }, } }
通用钩子
以下钩子在开发和构建模式下都会执行:
resolveId
resolveId(source: string, importer: string | undefined, options: { isEntry: boolean }): string | null | { id: string; external?: boolean }
自定义模块解析逻辑。返回解析后的 ID,或 null 交给下一个插件处理。
load
load(id: string): string | null | { code: string; map?: any }
自定义模块加载。返回模块源码,或 null 使用默认加载。
transform
transform(code: string, id: string): string | null | { code: string; map?: any }
转换模块代码。代码会按插件顺序依次通过 transform 管道。
buildStart / buildEnd
buildStart(): void buildEnd(error?: Error): void
构建生命周期钩子。
Nasti / Vite 专有钩子
config
config(config: NastiConfig, env: { mode: string; command: string }): NastiConfig | null
在配置解析前修改配置。
configResolved
configResolved(config: ResolvedConfig): void
读取最终配置。
configureServer
configureServer(server: DevServer): void | (() => void)
自定义开发服务器。返回函数会在内部中间件之后执行。
transformIndexHtml
transformIndexHtml(html: string): string | HtmlTagDescriptor[] | { html: string; tags: HtmlTagDescriptor[] }
转换入口 HTML 文件。
handleHotUpdate
handleHotUpdate(ctx: HmrContext): void | ModuleNode[]
自定义 HMR 更新处理。
插件 setup 与跨插件 API
setup(api) 每次配置解析只执行一次。插件可通过
api.expose() / api.useExposed() 共享能力,
并通过 pre / post 声明 setup 依赖顺序。
const key = Symbol.for('example.config') const provider = { name: 'example:provider', setup(api) { api.expose(key, { enabled: true }) }, } const consumer = { name: 'example:consumer', pre: ['example:provider'], setup(api) { const config = api.useExposed(key) }, }
Environment Driver:Rspeedy bridge
环境声明 driver 后不进入 Nasti 的 Rolldown 流水线,而由插件提供
build / serve / watchChange /
close。这适合 Vue Lynx:插件可以调用
@lynx-js/rspeedy 的 createRspeedy(),保留其
Rspack layer、CSS extractor、HMR 与 Lynx bundle encoder。
import { defineConfig } from '@nasti-toolchain/nasti' import { pluginRspeedyBridge } from 'nasti-plugin-rspeedy' export default defineConfig({ environments: { lynx: { consumer: 'client', driver: 'rspeedy', }, }, plugins: [pluginRspeedyBridge()], })
bridge 插件的最小形态:
const pluginRspeedyBridge = () => ({ name: 'nasti:rspeedy', async createEnvironmentDriver(environment) { if (environment.options.driver !== 'rspeedy') return const { createRspeedy } = await import('@lynx-js/rspeedy') let instance return { name: 'rspeedy', async build({ config }) { instance = await createRspeedy({ cwd: config.root }) // 调用 Rspeedy build,并把产物归一为 EnvironmentBuildResult return { output: [] } }, async serve({ config }) { // 启动 Rspeedy dev server,返回 localUrls / networkUrls return { localUrls: [] } }, watchChange(file, event) {}, async close() {}, } }, afterBuildApp(results, api, context) { // 通过 context 跨环境读取 entries / manifest / stats 并聚合产物 }, })
插件顺序
插件按以下顺序执行:
enforce: 'pre'的插件- 没有 enforce 的普通插件
enforce: 'post'的插件
在上述稳定顺序之上,pre: ['plugin-name'] 表示列出的插件必须先完成
setup,post 表示列出的插件必须后完成 setup。检测到依赖环时配置解析会失败。
条件应用
使用 apply 让插件只在特定模式下生效:
{
apply: 'build', // 仅在 nasti build 时生效
apply: 'serve', // 仅在 nasti dev 时生效
apply: (config, { command }) => command === 'build', // 函数形式
}示例:Markdown 插件
function markdownPlugin(): NastiPlugin { return { name: 'markdown', transform(code, id) { if (!id.endsWith('.md')) return null const html = marked(code) return `export default ${JSON.stringify(html)}` }, } }