Plugin Hooks
本章介绍关于 Modern.js Module 支持的生命周期钩子。
目前主要包含以下几类生命周期钩子:
- 配置钩子:用于处理用户配置。
- 构建钩子:仅在执行
build
命令构建源码产物时触发。
buildPlatform
钩子:仅在执行 build --platform
命令生成其他构建产物时触发。
- 调试钩子:运行
dev
命令时会触发的钩子。
这里详细解释了 Hook 模型
配置钩子
resolveModuleUserConfig
用于修改用户配置。
类型:AsyncWaterfall
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
resolveModuleUserConfig(config: ModuleUserConfig): ModuleUserConfig {},
};
},
});
构建钩子
在执行 build
命令的时候,会按照顺序触发以下 Hooks:
beforeBuild
beforeBuildTask
afterBuildTask
afterBuild
beforeBuild
执行整体构建流程之前触发。
类型:ParallelWorkflow
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
beforeBuild(options: Options): void {},
};
},
});
参数类型:
type Options = {
options: { config: BaseBuildConfig[]; cliOptions: BuildCommandOptions };
};
export interface BuildCommandOptions {
config: string;
clear?: boolean;
dts?: boolean;
platform?: boolean | string[];
tsconfig: string;
watch?: boolean;
}
BuildConfig
类型参考 API 配置
beforeBuildTask
根据构建配置,Modern.js Module 会将整体构建分成多个子构建任务。该 Hook 将会在每一个构建子任务之前触发。
类型:AsyncWaterfall
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
beforeBuildTask(config: BaseBuildConfig): BaseBuildConfig {
return config;
},
};
},
});
afterBuildTask
类型:ParallelWorkflow
,每一个构建子任务结束之后触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
afterBuildTask(options: BuildTaskResult): void {
// ...
},
};
},
});
参数和返回值类型:
export interface BuildTaskResult {
status: 'success' | 'fail';
message?: string;
config: BaseBuildConfig;
}
afterBuild
类型:ParallelWorkflow
,整体构建流程结束之后触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
afterBuild(options: BuildResult): void {
// ...
},
};
},
});
参数和返回值类型:
export interface BuildResult {
status: 'success' | 'fail';
message?: string;
config: BuildConfig;
commandOptions: BuildCommandOptions;
totalDuration: number;
}
buildPlatform 钩子
module-tools 还提供了 build --platform
命令来执行特定的构建任务。
例如在安装了 Doc 插件后,就可以执行 build --platform
或者 build --platform doc
来执行 doc 的构建任务。因为 doc 插件基于 buildPlatform Hooks 实现了该功能。
在执行 build --platform
后会按照以下顺序触发 Hooks:
registerBuildPlatform
beforeBuildPlatform
buildPlatform
afterBuildPlatform
registerBuildPlatform
获取在执行 build --platform
命令时候需要运行的任务信息。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
registerBuildPlatform(): RegisterBuildPlatformResult {
// ...
return {
platform: 'doc',
build() {
// logic
},
};
},
};
},
});
入参和返回的参数类型:
export interface RegisterBuildPlatformResult {
platform: string | string[];
build: (
currentPlatform: string, // 当前运行的 platform 构建任务
context: { isTsProject: boolean },
) => void | Promise<void>;
}
beforeBuildPlatform
当执行 build --platform
命令的时候,会触发所有已注册的构建任务。beforeBuildPlatform
会在执行整体的构建任务之前触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
beforeBuildPlatform(platforms: RegisterBuildPlatformResult[]): void {
console.info(`have ${platforms.length} platform tasks`);
},
};
},
});
入参和返回的参数类型:
export interface RegisterBuildPlatformResult {
platform: string | string[];
build: (
currentPlatform: string, // 当前运行的 platform 构建任务
context: { isTsProject: boolean },
) => void | Promise<void>;
}
buildPlatform
当执行 build --platform
命令的时候,会触发所有已注册的构建任务。buildPlatform
会在每个构建任务执行之前触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
buildPlatform({ platform }: Options): void {
console.info(`current task is ${platform}`);
},
};
},
});
入参和返回的参数类型:
export interface Options {
platform: string;
}
afterBuildPlatform
当执行 build --platform
命令的时候,会触发所有已注册的构建任务。afterBuildPlatform
会在整体 platform 构建任务结束后触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
afterBuildPlatform(result: BuildPlatformResult): void {
if (result.status === 'success') {
console.info(`all platform build task success`);
} else {
console.error(result.message);
}
},
};
},
});
入参和返回的参数类型:
export interface BuildPlatformResult {
status: 'success' | 'fail';
message: string | Error | null;
}
调试钩子
在执行 dev
命令的时候,会按照顺序触发以下 Hooks:
registerDev
: 在获取调试功能信息的时候触发。
beforeDev
: 开始执行调试整体流程之前触发。
beforeDevMenu
: 出现调试列表/菜单之前触发。
afterDevMenu
: 选择调试列表/菜单选项后触发。
beforeDevTask
: 执行调试任务之前触发。
afterDev
: 执行 dev 整体流程最后触发。
registerDev
注册调试工具相关的数据。主要包含:
- 调试工具的名称
- 显示在菜单列表中的项目名称以及对应的值。
dev
子命令的定义。
- 是否在运行调试任务之前执行源码构建
- 执行调试任务的函数。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
registerDev() {
return {
// 调试工具名称
name: 'storybook',
// 菜单显示内容
menuItem: {
name: 'Storybook',
value: 'storybook',
},
// 定义的 dev 子命令
subCommands: ['storybook', 'story'],
async action() {
// dev logic
},
};
},
};
},
});
入参和返回的参数类型:
export interface DevToolData {
name: string;
subCommands?: string[];
menuItem?: {
name: string;
value: string;
};
action: (
options: { port?: string },
context: { isTsProject?: boolean },
) => void | Promise<void>;
}
beforeDev
在收集完所有调试工具元数据后,执行 dev 任务之前触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
beforeDev(metas: DevToolData[]) {
console.info(`have ${metas.length} dev tools`);
},
};
},
});
入参和返回的参数类型:
export interface DevToolData {
name: string;
subCommands?: string[];
menuItem?: {
name: string;
value: string;
};
action: (
options: { port?: string },
context: { isTsProject?: boolean },
) => void | Promise<void>;
}
beforeDevMenu
在出现调试列表/菜单之前触发。接收 inquirer question 作为参数。默认值为:
const question = [
{
name: 'choiceDevTool',
message: '选择调试工具',
type: 'list',
// 注册的调试信息
choices,
},
];
afterDevMenu
选择调试列表/菜单选项后触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
beforeDevMenu(questions) {
questions[0].message += '!';
return questions; // required
},
afterDevMenu(options: Options) {
console.info(`choise ${options.result.choiceDevTool} dev tools`);
},
};
},
});
入参和返回的参数类型:
export type { QuestionCollection } from 'inquirer';
export interface Options {
result: PromptResult;
devTools: DevToolData[];
}
export type PromptResult = { choiceDevTool: string };
export interface DevToolData {
name: string;
subCommands?: string[];
menuItem?: {
name: string;
value: string;
};
action: (
options: { port?: string },
context: { isTsProject?: boolean },
) => void | Promise<void>;
}
beforeDevTask
执行调试任务之前触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
beforeDevTask(currentDevData: DevToolData) {
console.info(`${currentDevData.name} running`);
},
};
},
});
入参和返回的参数类型:
export interface DevToolData {
name: string;
subCommands?: string[];
menuItem?: {
name: string;
value: string;
};
action: (
options: { port?: string },
context: { isTsProject?: boolean },
) => void | Promise<void>;
}
afterDev
在中断调试任务进程时触发。
export const myPlugin = (): CliPlugin<ModuleTools> => ({
name: 'my-plugin',
setup() {
return {
afterDev() {
console.info(`exit!`);
},
};
},
});