Hook 列表
Modern.js 工程体系中包含三类插件:CLI、Runtime、Server,每一类插件可以使用不同的 Hooks。
在本章节中,罗列了所有可用的 Hooks,你可以根据自己的需求来使用对应的 Hook。
CLI Common Hooks
以下是通用的 CLI Hooks,可以在 Modern.js Framework 以及 Modern.js Module 中使用。
beforeConfig
- 功能:运行收集配置前的任务
- 执行阶段:收集配置前
- Hook 模型:
AsyncWorkflow
- 类型:
AsyncWorkflow<void, void>
- 使用示例:
import type { CliPlugin } from '@modern-js/core';
export const myPlugin = (): CliPlugin => ({
setup(api) {
return {
beforeConfig: () => {
// do something
},
};
},
});
config
- 功能:收集配置
- 执行阶段:解析完
modern.config.ts
中的配置之后
- Hook 模型:
ParallelWorkflow
- 类型:
ParallelWorkflow<void, unknown>
- 使用示例:
import type { CliPlugin } from '@modern-js/core';
export const myPlugin = (): CliPlugin => ({
setup(api) {
return {
config: () => {
return {
/** some config */
};
},
};
},
});
如果你需要设置 Modern.js Framework 的配置,请使用 @modern-js/app-tools
导出的 CliPlugin<AppTools>
类型:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin => ({
setup(api) {
return {
config: () => {
return {
output: {
polyfill: 'usage',
},
};
},
};
},
});
插件在 config
hook 中返回的配置信息,会被 Modern.js 统一收集与合并,最终生成一份 NormalizedConfig
。在进行配置合并时,优先级由高到低依次为:
- 用户在
modern.config.*
文件里定义的配置
- 插件通过
config
hook 定义的配置
- Modern.js 默认配置。
prepare
- 功能:运行主流程的前置准备流程
- 执行阶段:校验完配置之后
- Hook 模型:
AsyncWorkflow
- 类型:
AsyncWorkflow<void, void>
- 使用示例:
import type { CliPlugin } from '@modern-js/core';
export const myPlugin = (): CliPlugin => ({
setup(api) {
return {
prepare: () => {
// do something
},
};
},
});
afterPrepare
- 功能:运行前置准备流程的之后的任务
- 执行阶段:前置准备流程之后
- Hook 模型:
AsyncWorkflow
- 类型:
AsyncWorkflow<void, void>
- 使用示例:
import type { CliPlugin } from '@modern-js/core';
export const myPlugin = (): CliPlugin => ({
setup(api) {
return {
afterPrepare: () => {
// do something
},
};
},
});
commands
- 功能:为 commander 添加新的 CLI 命令
- 执行阶段:
prepare
Hook 运行完成之后
- Hook 模型:
AsyncWorkflow
- 类型:
AsyncWorkflow<{ program: Command; }, void>
- 使用示例:
import type { CliPlugin } from '@modern-js/core';
export const myPlugin = (): CliPlugin => ({
setup(api) {
return {
commands: ({ program }) => {
program.command('foo').action(async () => {
// do something
console.log('foo');
});
},
};
},
});
将上面这个插件添加到 modern.config.ts
中:
modern.config.ts
import myPlugin from './config/plugin/myPlugin';
export const myPlugin = defineConfig({
plugins: [myPlugin()],
});
运行 modern foo
就可以看到控制台输出:
beforeExit
- 功能:在退出进程前,重置一些文件状态
- 执行阶段:进程退出之前
- Hook 模型:
Workflow
- 类型:
Workflow<void, void>
- 使用示例:
import type { CliPlugin } from '@modern-js/core';
export const myPlugin = (): CliPlugin => ({
setup(api) {
return {
beforeExit: () => {
// do something
},
};
},
});
TIP
由于 Node.js 中退出进程时的回调函数是同步的,所以 beforeExit
Hook 的类型是 Workflow
,不能执行异步操作。
CLI Framework Hooks
以下是框架的 CLI Hooks,只能在 Modern.js Framework 中使用,不能在 Modern.js Module 中使用。
你需要从 @modern-js/app-tools
中导入 CliPlugin
和 AppTools
类型,以获得准确的 Hooks 类型提示。
beforeDev
- 功能:运行 dev 主流程的之前的任务
- 执行阶段:
dev
命令运行时,项目开始启动前执行
- Hook 模型:
AsyncWorkflow
- 类型:
AsyncWorkflow<void, unknown>
- 使用示例:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
beforeDev: () => {
// do something
},
};
},
});
afterDev
- 功能:运行 dev 主流程的之后的任务
- 执行阶段:运行
dev
命令时,每一次编译完成后执行
- Hook 模型:
AsyncWorkflow
- 类型:
AsyncWorkflow<{ isFirstCompile: boolean }, unknown>
- 使用示例:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
afterDev: () => {
// do something
},
};
},
});
afterDev
会在每一次编译完成后执行,你可以通过 isFirstCompile
参数来判断是否为首次编译:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
afterDev: ({ isFirstCompile }) => {
if (isFirstCompile) {
// do something
}
},
};
},
});
beforeBuild
- 功能:在执行生产环境构建前触发的回调函数,你可以通过
bundlerConfigs
参数获取到底层打包工具的最终配置数组。
- 如果当前打包工具为 webpack,则获取到的是 webpack 配置数组。
- 如果当前打包工具为 Rspack,则获取到的是 Rspack 配置数组。
- 配置数组中可能包含一份或多份配置,这取决于你是否开启了 SSR 等功能。
- 执行阶段:运行
build
命令后,在开始构建前执行
- Hook 模型:
AsyncWorkflow
- 类型:
type BeforeBuild = AsyncWorkflow<{
bundlerConfigs: WebpackConfig[] | RspackConfig[];
}>;
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
beforeBuild: ({ bundlerConfigs }) => {
console.log('Before build.');
console.log(bundlerConfigs);
},
};
},
});
afterBuild
- 功能:在执行生产环境构建后触发的回调函数,你可以通过
stats
参数获取到构建结果信息。
- 如果当前打包工具为 webpack,则获取到的是 webpack Stats。
- 如果当前打包工具为 Rspack,则获取到的是 Rspack Stats。
- 执行阶段:运行
build
命令运行后,在项目构建完成之后执行
- Hook 模型:
AsyncWorkflow
- 类型:
type AfterBuild = AsyncWorkflow<{
stats?: Stats | MultiStats;
}>;
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
afterBuild: ({ stats }) => {
console.log('After build.');
console.log(stats);
},
};
},
});
beforeCreateCompiler
- 功能:在创建底层 Compiler 实例前触发的回调函数,并且你可以通过
bundlerConfigs
参数获取到底层打包工具的最终配置数组:
- 如果当前打包工具为 webpack,则获取到的是 webpack 配置数组。
- 如果当前打包工具为 Rspack,则获取到的是 Rspack 配置数组。
- 配置数组中可能包含一份或多份配置,这取决于你是否开启了 SSR 等功能。
- 执行阶段:在执行 dev 或 build 命令时,创建 Compiler 实例之前执行
- Hook 模型:
AsyncWorkflow
- 类型:
type BeforeCreateCompiler = AsyncWorkflow<
{ bundlerConfigs: Configuration[] },
unknown
>;
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
beforeCreateCompiler: ({ bundlerConfigs }) => {
console.log('Before create compiler.');
console.log(bundlerConfigs);
},
};
},
});
afterCreateCompiler
- 功能:在创建 Compiler 实例后、执行构建前触发的回调函数,并且你可以通过
compiler
参数获取到 Compiler 实例对象:
- 如果当前打包工具为 webpack,则获取到的是 webpack Compiler 对象。
- 如果当前打包工具为 Rspack,则获取到的是 Rspack Compiler 对象。
- 执行阶段:创建 Compiler 对象之后执行
- Hook 模型:
AsyncWorkflow
- 类型:
type AfterCreateCompiler = AsyncWorkflow<
{ compiler: Compiler | MultiCompiler | undefined },
unknown
>;
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
afterCreateCompiler: ({ compiler }) => {
console.log('After create compiler.');
console.log(compiler);
},
};
},
});
beforePrintInstructions
- 功能:在中间件函数中可以拿到即将打印的日志信息,并对其进行修改
- 执行阶段:打印日志信息之前执行
- Hook 模型:
AsyncWaterfall
- 类型:
AsyncWaterfall<{ instructions: string }>
- 使用示例:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
beforePrintInstructions: ({ instructions }) => {
// do something
return {
instructions: [...instructions, 'some new message'],
};
},
};
},
});
modifyFileSystemRoutes
- 功能:用于修改生成前端页面路由文件中的内容,内容都是需要可序列化的
- 执行阶段:生成前端路由文件之前,
prepare
阶段触发
- Hook 模型:
AsyncWaterfall
- 类型:
AsyncWaterfall<{ entrypoint: Entrypoint; routes: Route[]; }>
- 使用示例:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
modifyFileSystemRoutes({ entrypoint, routes }) {
return {
entrypoint,
routes: [
...routes,
{
path: '/custom_page',
component: require.resolve('./Component'),
exact: true,
},
],
};
},
};
},
});
这样就为前端新增了一个页面路由。
modifyServerRoutes
- 功能:用于修改生成服务器路由中的内容
- 执行阶段:生成 Server 路由文件之前,
prepare
阶段触发
- Hook 模型:
AsyncWaterfall
- 类型:
AsyncWaterfall<{ routes: ServerRoute[]; }>
- 使用示例:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
modifyServerRoutes({ routes }) {
return {
routes: [
...routes,
{
urlPath: '/api/foo',
isApi: true,
entryPath: '',
isSPA: false,
isSSR: false,
},
],
};
},
};
},
});
htmlPartials
- 功能:用于定制生成的 HTML 页面模版
- 执行阶段:
prepare
阶段触发
- Hook 模型:
AsyncWaterfall
- 类型:
AsyncWaterfall<{ entrypoint: Entrypoint; partials: HtmlPartials; }>
- 使用示例:
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
export const myPlugin = (): CliPlugin<AppTools> => ({
setup(api) {
return {
async htmlPartials({ entrypoint, partials }) {
partials.head.push('<script>console.log("test")</script>');
return {
entrypoint,
partials,
};
},
};
},
});
这样就为 HTML 模版中新增了一个 Script 标签。
Runtime
NOTE
目前 Runtime 插件还未完全开放,API 不保证稳定,使用需谨慎。
Runtime 插件主要用于开发者自定义应用渲染前行为和修改需要渲染的组件。
beforeRender
- 功能:在应用渲染之前增加行为
- 执行阶段:渲染(SSR/CSR)
- Hook 模型:
AsyncWorkflow
- 类型:
AsyncWorkflow<RuntimeContext, void>
- 使用示例:
import type { Plugin } from '@modern-js/runtime';
export const myPlugin = (): Plugin => ({
setup(api) {
return {
beforeRender(context) {
// do something
},
};
},
});
wrapRoot
- 功能:修改需要渲染的组件
- 执行阶段:渲染(SSR/CSR)
- Hook 模型:
Waterfall
- 类型:
Waterfall<React.ComponentType<any>>
- 使用示例:
import { createContext } from 'react';
import type { Plugin } from '@modern-js/runtime';
export const myPlugin = (): Plugin => ({
setup(api) {
const FooContext = createContext('');
return {
wrapRoot(App) {
const AppWrapper = (props: any) => {
return (
<FooContext.Provider store={'test'}>
<App {...props} />
</FooContext.Provider>
);
};
return AppWrapper
},
};
},
});