@modern-js/main-doc 2.65.5 → 2.66.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/en/apis/app/hooks/src/app.mdx +20 -34
- package/docs/en/apis/app/hooks/src/modern.runtime.mdx +9 -0
- package/docs/en/apis/app/runtime/app/define-config.mdx +6 -0
- package/docs/en/community/blog/v2-release-note.mdx +1 -1
- package/docs/en/components/enable-micro-frontend.mdx +20 -3
- package/docs/en/components/micro-runtime-config.mdx +12 -13
- package/docs/en/components/reduck-notify.mdx +27 -0
- package/docs/en/configure/app/plugins.mdx +2 -2
- package/docs/en/configure/app/runtime/0-intro.mdx +63 -91
- package/docs/en/configure/app/tools/esbuild.mdx +1 -1
- package/docs/en/configure/app/tools/swc.mdx +1 -1
- package/docs/en/configure/app/usage.mdx +93 -69
- package/docs/en/guides/basic-features/render/_meta.json +1 -1
- package/docs/en/guides/basic-features/render/before-render.mdx +115 -0
- package/docs/en/guides/basic-features/routes.mdx +0 -95
- package/docs/en/guides/topic-detail/micro-frontend/c02-development.mdx +3 -5
- package/docs/en/guides/topic-detail/micro-frontend/c03-main-app.mdx +4 -2
- package/docs/en/guides/topic-detail/model/auto-actions.mdx +0 -4
- package/docs/en/guides/topic-detail/model/computed-state.mdx +0 -5
- package/docs/en/guides/topic-detail/model/define-model.mdx +0 -4
- package/docs/en/guides/topic-detail/model/faq.mdx +0 -5
- package/docs/en/guides/topic-detail/model/manage-effects.mdx +0 -5
- package/docs/en/guides/topic-detail/model/model-communicate.mdx +0 -5
- package/docs/en/guides/topic-detail/model/performance.mdx +0 -4
- package/docs/en/guides/topic-detail/model/quick-start.mdx +5 -7
- package/docs/en/guides/topic-detail/model/redux-integration.mdx +0 -4
- package/docs/en/guides/topic-detail/model/typescript-best-practice.mdx +0 -4
- package/docs/en/guides/topic-detail/model/use-model.mdx +0 -5
- package/docs/en/guides/topic-detail/model/use-out-of-modernjs.mdx +0 -4
- package/docs/en/plugin/_meta.json +8 -7
- package/docs/en/plugin/cli-plugins/_meta.json +1 -1
- package/docs/en/plugin/cli-plugins/api.mdx +617 -0
- package/docs/en/plugin/cli-plugins/life-cycle.mdx +139 -0
- package/docs/en/plugin/cli-plugins/migration.mdx +98 -0
- package/docs/en/plugin/introduction.mdx +119 -47
- package/docs/en/plugin/official/_meta.json +12 -0
- package/docs/en/plugin/official/cli-plugins/_meta.json +1 -0
- package/docs/en/plugin/official/cli-plugins.mdx +6 -0
- package/docs/en/plugin/official/rsbuild-plugins.mdx +3 -0
- package/docs/en/plugin/plugin-system.mdx +237 -0
- package/docs/en/plugin/runtime-plugins/_meta.json +1 -0
- package/docs/en/plugin/runtime-plugins/api.mdx +165 -0
- package/docs/en/plugin/runtime-plugins/life-cycle.mdx +29 -0
- package/docs/en/plugin/runtime-plugins/migration.mdx +101 -0
- package/docs/en/plugin/server-plugins/api.mdx +3 -0
- package/docs/en/plugin/server-plugins/life-cycle.mdx +3 -0
- package/docs/zh/apis/app/hooks/src/app.mdx +18 -26
- package/docs/zh/apis/app/hooks/src/modern.runtime.mdx +9 -0
- package/docs/zh/apis/app/runtime/app/define-config.mdx +5 -0
- package/docs/zh/community/blog/v2-release-note.mdx +1 -1
- package/docs/zh/components/enable-micro-frontend.mdx +19 -12
- package/docs/zh/components/micro-runtime-config.mdx +3 -3
- package/docs/zh/components/reduck-notify.mdx +27 -0
- package/docs/zh/configure/app/plugins.mdx +2 -2
- package/docs/zh/configure/app/runtime/0-intro.mdx +67 -86
- package/docs/zh/configure/app/tools/esbuild.mdx +1 -1
- package/docs/zh/configure/app/tools/swc.mdx +1 -1
- package/docs/zh/configure/app/usage.mdx +44 -21
- package/docs/zh/guides/basic-features/render/_meta.json +1 -1
- package/docs/zh/guides/basic-features/render/before-render.mdx +115 -0
- package/docs/zh/guides/basic-features/routes.mdx +0 -95
- package/docs/zh/guides/topic-detail/micro-frontend/c02-development.mdx +3 -5
- package/docs/zh/guides/topic-detail/micro-frontend/c03-main-app.mdx +4 -2
- package/docs/zh/guides/topic-detail/model/auto-actions.mdx +0 -4
- package/docs/zh/guides/topic-detail/model/computed-state.mdx +0 -4
- package/docs/zh/guides/topic-detail/model/define-model.mdx +1 -4
- package/docs/zh/guides/topic-detail/model/faq.mdx +0 -5
- package/docs/zh/guides/topic-detail/model/manage-effects.mdx +0 -4
- package/docs/zh/guides/topic-detail/model/model-communicate.mdx +1 -4
- package/docs/zh/guides/topic-detail/model/performance.mdx +0 -4
- package/docs/zh/guides/topic-detail/model/quick-start.mdx +7 -8
- package/docs/zh/guides/topic-detail/model/redux-integration.mdx +0 -4
- package/docs/zh/guides/topic-detail/model/typescript-best-practice.mdx +0 -4
- package/docs/zh/guides/topic-detail/model/use-model.mdx +0 -5
- package/docs/zh/guides/topic-detail/model/use-out-of-modernjs.mdx +0 -4
- package/docs/zh/plugin/_meta.json +8 -7
- package/docs/zh/plugin/cli-plugins/_meta.json +1 -1
- package/docs/zh/plugin/cli-plugins/api.mdx +617 -0
- package/docs/zh/plugin/cli-plugins/life-cycle.mdx +139 -0
- package/docs/zh/plugin/cli-plugins/migration.mdx +98 -0
- package/docs/zh/plugin/introduction.mdx +92 -20
- package/docs/zh/plugin/official/_meta.json +12 -0
- package/docs/zh/plugin/official/cli-plugins/_meta.json +1 -0
- package/docs/zh/plugin/official/cli-plugins.mdx +6 -0
- package/docs/zh/plugin/official/rsbuild-plugins.mdx +3 -0
- package/docs/zh/plugin/plugin-system.mdx +239 -0
- package/docs/zh/plugin/runtime-plugins/_meta.json +1 -0
- package/docs/zh/plugin/runtime-plugins/api.mdx +166 -0
- package/docs/zh/plugin/runtime-plugins/life-cycle.mdx +29 -0
- package/docs/zh/plugin/runtime-plugins/migration.mdx +101 -0
- package/docs/zh/plugin/server-plugins/api.mdx +3 -0
- package/docs/zh/plugin/server-plugins/life-cycle.mdx +3 -0
- package/i18n.json +4 -0
- package/package.json +3 -2
- package/src/components/Footer/index.tsx +1 -1
- package/src/components/Mermaid/index.tsx +60 -0
- package/src/components/Mermaid/style.scss +221 -0
- package/docs/en/plugin/cli-plugins.mdx +0 -6
- package/docs/en/plugin/plugin-system/_meta.json +0 -10
- package/docs/en/plugin/plugin-system/extend.mdx +0 -163
- package/docs/en/plugin/plugin-system/hook-list.mdx +0 -711
- package/docs/en/plugin/plugin-system/hook.mdx +0 -188
- package/docs/en/plugin/plugin-system/implement.mdx +0 -243
- package/docs/en/plugin/plugin-system/introduction.mdx +0 -95
- package/docs/en/plugin/plugin-system/lifecycle.mdx +0 -16
- package/docs/en/plugin/plugin-system/plugin-api.mdx +0 -138
- package/docs/en/plugin/plugin-system/relationship.mdx +0 -119
- package/docs/en/plugin/rsbuild-plugins.mdx +0 -3
- package/docs/zh/plugin/cli-plugins.mdx +0 -6
- package/docs/zh/plugin/plugin-system/_meta.json +0 -10
- package/docs/zh/plugin/plugin-system/extend.mdx +0 -163
- package/docs/zh/plugin/plugin-system/hook-list.mdx +0 -715
- package/docs/zh/plugin/plugin-system/hook.mdx +0 -173
- package/docs/zh/plugin/plugin-system/implement.mdx +0 -250
- package/docs/zh/plugin/plugin-system/introduction.mdx +0 -94
- package/docs/zh/plugin/plugin-system/lifecycle.mdx +0 -16
- package/docs/zh/plugin/plugin-system/plugin-api.mdx +0 -138
- package/docs/zh/plugin/plugin-system/relationship.mdx +0 -119
- package/docs/zh/plugin/rsbuild-plugins.mdx +0 -4
- /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-bff.mdx +0 -0
- /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-ssg.mdx +0 -0
- /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-swc.mdx +0 -0
- /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-tailwind.mdx +0 -0
- /package/docs/en/plugin/{rsbuild-plugins → official/rsbuild-plugins}/_meta.json +0 -0
- /package/docs/en/plugin/{rsbuild-plugins → official/rsbuild-plugins}/plugin-esbuild.mdx +0 -0
- /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-bff.mdx +0 -0
- /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-ssg.mdx +0 -0
- /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-swc.mdx +0 -0
- /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-tailwind.mdx +0 -0
- /package/docs/zh/plugin/{rsbuild-plugins → official/rsbuild-plugins}/_meta.json +0 -0
- /package/docs/zh/plugin/{rsbuild-plugins → official/rsbuild-plugins}/plugin-esbuild.mdx +0 -0
@@ -0,0 +1,239 @@
|
|
1
|
+
# 插件系统
|
2
|
+
|
3
|
+
Modern.js 采用高度可扩展的插件化架构,其核心功能和扩展能力均通过插件实现。插件系统不仅保证了框架的灵活性,也为开发者提供了强大的定制化手段。本文将重点介绍如何编写 Modern.js 插件,帮助您快速上手插件开发。
|
4
|
+
|
5
|
+
## 核心理念:一切皆插件
|
6
|
+
|
7
|
+
Modern.js 秉承“一切皆插件”的设计哲学,将框架的各项功能模块化,通过插件的形式进行组装和扩展。这种设计带来了诸多优势,包括:
|
8
|
+
|
9
|
+
- **高内聚,低耦合**:各功能模块独立开发、测试和维护,降低系统复杂度。
|
10
|
+
- **灵活可扩展**:用户可通过编写或组合插件,轻松定制框架行为,无需修改核心代码。
|
11
|
+
- **易于复用**:插件可跨项目共享,提高开发效率。
|
12
|
+
- **渐进式增强**:按需引入插件,无需一开始就承载所有功能的复杂性。
|
13
|
+
|
14
|
+
## 插件类型与适用场景
|
15
|
+
|
16
|
+
Modern.js 提供了三种主要插件类型,分别对应应用开发的不同阶段:
|
17
|
+
|
18
|
+
**CLI 插件**:
|
19
|
+
- **作用阶段**:构建时(执行 `modern` 命令时)。
|
20
|
+
- **典型场景**:
|
21
|
+
- 扩展命令行工具。
|
22
|
+
- 修改构建配置。
|
23
|
+
- 监听文件变化。
|
24
|
+
- 控制构建流程。
|
25
|
+
- **配置方式**:`modern.config.ts` 中的 `plugins` 字段。
|
26
|
+
|
27
|
+
**Runtime 插件**:
|
28
|
+
- **作用阶段**:应用运行时(浏览器/Node.js 环境)。
|
29
|
+
- **典型场景**:
|
30
|
+
- 初始化全局状态或服务。
|
31
|
+
- 封装 React 高阶组件(HOC)。
|
32
|
+
- 拦截或修改路由行为。
|
33
|
+
- 控制渲染流程。
|
34
|
+
- **配置方式**:`src/modern.runtime.ts` 中的 `plugins` 字段。
|
35
|
+
|
36
|
+
{/* **Server 插件**:
|
37
|
+
- **作用阶段**:服务端请求处理阶段。
|
38
|
+
- **典型场景**:
|
39
|
+
- 添加自定义中间件。
|
40
|
+
- 扩展服务端 API。
|
41
|
+
- 定制化 SSR 逻辑。
|
42
|
+
- 与后端框架集成。
|
43
|
+
- **配置方式**:`server/modern.server.ts` 中的 `plugins` 字段。 */}
|
44
|
+
|
45
|
+
## 插件结构
|
46
|
+
|
47
|
+
一个典型的 Modern.js 插件包含以下几个关键部分:
|
48
|
+
|
49
|
+
```ts
|
50
|
+
import type { Plugin } from '@modern-js/plugin-v2';
|
51
|
+
|
52
|
+
const myPlugin: Plugin = {
|
53
|
+
name: 'my-awesome-plugin', // 插件的唯一标识符(必需)
|
54
|
+
|
55
|
+
// 插件依赖和执行顺序(可选)
|
56
|
+
pre: [], // 在此插件之前执行的插件名列表,默认为空数组
|
57
|
+
post: [], // 在此插件之后执行的插件名列表,默认为空数组
|
58
|
+
required: [],// 必需的插件列表,若依赖的插件未注册,则会报错,默认为空数组
|
59
|
+
usePlugins: [], // 内部使用的插件实例列表,默认为空数组
|
60
|
+
|
61
|
+
// 注册新的 Hook (可选)
|
62
|
+
registryHook: {},
|
63
|
+
|
64
|
+
// 插件的入口函数(必需)
|
65
|
+
setup(api) {
|
66
|
+
// 插件的核心逻辑,通过 api 对象调用插件 API
|
67
|
+
api.modifyWebpackConfig(config => { /* ... */ });
|
68
|
+
api.onPrepare(() => { /* ... */ });
|
69
|
+
// ... 其他 API 调用
|
70
|
+
},
|
71
|
+
};
|
72
|
+
|
73
|
+
export default myPlugin;
|
74
|
+
```
|
75
|
+
|
76
|
+
**字段说明:**
|
77
|
+
|
78
|
+
##### `name`
|
79
|
+
|
80
|
+
- 类型: `string`
|
81
|
+
- 说明:标识插件的名称。在插件体系中,该名称必须唯一,否则将导致插件加载失败。
|
82
|
+
|
83
|
+
:::info
|
84
|
+
后续 `pre`, `post`, `required` 中声明的插件名称都是这里的 name 字段.
|
85
|
+
:::
|
86
|
+
|
87
|
+
##### `setup`
|
88
|
+
|
89
|
+
- 类型: `(api: PluginAPI) => MaybePromise<void>`
|
90
|
+
- 说明:插件逻辑的主要入口。
|
91
|
+
|
92
|
+
###### `api`
|
93
|
+
|
94
|
+
- 类型: `PluginAPI`
|
95
|
+
- 说明:插件的 API,包含插件支持的 Hooks 和工具函数。
|
96
|
+
|
97
|
+
##### `pre`
|
98
|
+
|
99
|
+
- 类型: `string[]`
|
100
|
+
- 说明:用于插入插件执行顺序。在 `pre` 中声明的插件会在此插件之前执行。
|
101
|
+
|
102
|
+
##### `post`
|
103
|
+
|
104
|
+
- 类型: `string[]`
|
105
|
+
- 说明:用于确定插件执行顺序。在 `post` 中声明的插件会在此插件之后执行。
|
106
|
+
|
107
|
+
##### `required`
|
108
|
+
|
109
|
+
- 类型: `string[]`
|
110
|
+
- 说明:该插件依赖的其它插件。在运行前,会校验依赖的插件是否已注册。
|
111
|
+
|
112
|
+
:::info
|
113
|
+
如果在 `pre` 或 `post` 中配置了未注册的插件名,这些插件名将被**自动忽略**,不会影响其他插件的执行。
|
114
|
+
|
115
|
+
如果需要明确声明当前插件依赖的插件必须存在,需要使用 `required` 字段。
|
116
|
+
:::
|
117
|
+
|
118
|
+
##### `usePlugins`
|
119
|
+
|
120
|
+
- 类型: `Plugin`
|
121
|
+
- 说明:主动在插件中注册其他相同类型的插件。
|
122
|
+
|
123
|
+
:::info
|
124
|
+
`usePlugins` 中声明的插件默认在当前插件之前执行。需要在其后执行,请使用 `post` 声明。
|
125
|
+
:::
|
126
|
+
|
127
|
+
##### `registryHooks`
|
128
|
+
|
129
|
+
- 类型: `Record<string, PluginHook<(...args: any[]) => any>>`
|
130
|
+
- 说明:扩展当前支持的 Hook 函数,以实现自定义功能。
|
131
|
+
|
132
|
+
|
133
|
+
## 插件 Hook 模型
|
134
|
+
|
135
|
+
Modern.js 插件系统的核心是其 Hook 模型,它定义了插件之间的通信机制。Modern.js 主要提供两种 Hook 类型:
|
136
|
+
|
137
|
+
### Async Hook(异步 Hook)
|
138
|
+
|
139
|
+
- **特点**:
|
140
|
+
- Hook 函数异步执行,支持 `async/await`。
|
141
|
+
- 前一个 Hook 函数的返回值会作为下一个 Hook 函数的第一个参数。
|
142
|
+
- 最终返回最后一个 Hook 函数的返回值。
|
143
|
+
- **适用场景**:涉及异步操作的场景(如网络请求、文件读写等)。
|
144
|
+
- **创建方式**:使用 `createAsyncHook` 创建。
|
145
|
+
|
146
|
+
示例:
|
147
|
+
|
148
|
+
```ts
|
149
|
+
// 定义 Hooks
|
150
|
+
import { createAsyncHook } from '@modern-js/plugin-v2';
|
151
|
+
|
152
|
+
export type AfterPrepareFn = () => Promise<void> | void;
|
153
|
+
export const onAfterPrepare = createAsyncHook<AfterPrepareFn>();
|
154
|
+
|
155
|
+
// 插件中注册 Hooks
|
156
|
+
const myPlugin = () => ({
|
157
|
+
name: "my-plugin",
|
158
|
+
registryHooks: {
|
159
|
+
onAfterPrepare,
|
160
|
+
},
|
161
|
+
setup: (api) => {
|
162
|
+
api.onPrepare(async () => {
|
163
|
+
// 插件中使用注册的 Hooks
|
164
|
+
const hooks = api.getHooks();
|
165
|
+
await hooks.onAfterPrepare.call();
|
166
|
+
});
|
167
|
+
}
|
168
|
+
});
|
169
|
+
|
170
|
+
// 在其他插件中使用 Hook
|
171
|
+
const myPlugin2 = () => ({
|
172
|
+
name: "my-plugin-2",
|
173
|
+
setup: (api) => {
|
174
|
+
api.onAfterPrepare(async () => {
|
175
|
+
// TOOD
|
176
|
+
});
|
177
|
+
}
|
178
|
+
})
|
179
|
+
```
|
180
|
+
|
181
|
+
### Sync Hook(同步 Hook)
|
182
|
+
|
183
|
+
- **特点**:
|
184
|
+
- Hook 函数同步执行。
|
185
|
+
- 前一个 Hook 函数的返回值会作为下一个 Hook 函数的第一个参数。
|
186
|
+
- 最终返回最后一个 Hook 函数的返回值。
|
187
|
+
- **适用场景**:需要同步修改数据的场景(如修改配置、路由等)。
|
188
|
+
- **创建方式**:使用 `createSyncHook` 创建。
|
189
|
+
|
190
|
+
示例:
|
191
|
+
|
192
|
+
```ts
|
193
|
+
// 定义 Hooks
|
194
|
+
import { createSyncHook } from '@modern-js/plugin-v2';
|
195
|
+
|
196
|
+
type RouteObject = {/** TODO **/};
|
197
|
+
const modifyRoutes = createSyncHook<(routes: RouteObject[]) => RouteObject[]>();
|
198
|
+
|
199
|
+
// 插件中注册 Hooks
|
200
|
+
const myPlugin = () => ({
|
201
|
+
name: "my-plugin",
|
202
|
+
registryHooks: {
|
203
|
+
modifyRoutes,
|
204
|
+
},
|
205
|
+
setup: (api) => {
|
206
|
+
api.onPrepare(async () => {
|
207
|
+
const routes = {};
|
208
|
+
// 在插件中使用注册的 Hooks
|
209
|
+
const hooks = api.getHooks();
|
210
|
+
const routesResult = hooks.modifyRoutes.call(routes);
|
211
|
+
});
|
212
|
+
}
|
213
|
+
});
|
214
|
+
|
215
|
+
// 其他插件使用 Hooks
|
216
|
+
const myPlugin2 = () => ({
|
217
|
+
name: "my-plugin",
|
218
|
+
setup: (api) => {
|
219
|
+
api.modifyRoutes(async (routes) => {
|
220
|
+
// 修改 routes
|
221
|
+
return routes;
|
222
|
+
});
|
223
|
+
}
|
224
|
+
});
|
225
|
+
```
|
226
|
+
|
227
|
+
## 插件开发最佳实践
|
228
|
+
|
229
|
+
- **单一职责**: 每个插件应该专注于实现一个特定的、内聚的功能。避免创建功能庞杂、职责不清的插件。
|
230
|
+
- **命名规范**: 插件名称应清晰、简洁, 并遵循一定的命名约定 (如 `plugin-xxx` 或 `@scope/plugin-xxx`).
|
231
|
+
- **类型安全**: 充分利用 TypeScript 的类型系统, 确保插件 API 的类型安全, 减少运行时错误。
|
232
|
+
- **文档完善**: 为插件编写清晰的文档, 包括 API 说明、使用示例、配置项解释以及变更日志。
|
233
|
+
- **测试充分**: 对插件进行单元测试和集成测试, 确保其稳定性、可靠性以及在各种场景下的兼容性。
|
234
|
+
- **减少副作用**: 插件应该尽可能地减少对外部环境的修改 (如全局变量、文件系统等), 保持插件的独立性和可移植性。
|
235
|
+
- **错误处理**: 插件内部应该妥善处理可能出现的错误, 避免因为插件的异常导致整个应用崩溃。
|
236
|
+
- **性能优化**: 注意插件的性能影响, 避免不必要的计算和资源消耗, 特别是在循环或频繁调用的 Hook 中。
|
237
|
+
- **版本控制**: 遵循语义化版本控制 (Semantic Versioning), 确保插件的向后兼容性, 方便用户升级。
|
238
|
+
|
239
|
+
遵循这些最佳实践, 可以帮助您开发出高质量、易维护、易使用的 Modern.js 插件。
|
@@ -0,0 +1 @@
|
|
1
|
+
["api", "life-cycle", "migration"]
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# 插件 API
|
2
|
+
|
3
|
+
Modern.js 的 Runtime 插件允许您在应用程序的 React 代码运行时扩展和修改其行为。通过 Runtime 插件,您可以轻松地执行初始化任务、实现 React 高阶组件(HOC)封装等功能。
|
4
|
+
|
5
|
+
## 插件结构
|
6
|
+
|
7
|
+
一个典型的 Runtime 插件如下所示:
|
8
|
+
|
9
|
+
```ts
|
10
|
+
import type { RuntimePluginFuture } from '@modern-js/runtime';
|
11
|
+
|
12
|
+
const myRuntimePlugin = (): RuntimePluginFuture => ({
|
13
|
+
name: 'my-runtime-plugin',
|
14
|
+
setup: (api) => {
|
15
|
+
// 使用 api 注册钩子
|
16
|
+
api.onBeforeRender((context) => {
|
17
|
+
console.log('Before rendering:', context);
|
18
|
+
});
|
19
|
+
|
20
|
+
api.wrapRoot((App) => {
|
21
|
+
return (props) => (
|
22
|
+
<MyContextProvider>
|
23
|
+
<App {...props} />
|
24
|
+
</MyContextProvider>
|
25
|
+
);
|
26
|
+
});
|
27
|
+
},
|
28
|
+
});
|
29
|
+
|
30
|
+
export default myRuntimePlugin;
|
31
|
+
|
32
|
+
```
|
33
|
+
|
34
|
+
- `name`: 插件的唯一标识符。
|
35
|
+
- `setup`: 插件的主要逻辑,接收一个 `api` 对象作为参数,用于注册钩子。
|
36
|
+
|
37
|
+
## API 概览
|
38
|
+
|
39
|
+
Runtime 插件 API 主要分为以下几类:
|
40
|
+
|
41
|
+
- **信息获取**:获取运行时配置和钩子函数。
|
42
|
+
- **生命周期钩子**:在应用渲染的不同阶段执行自定义逻辑。
|
43
|
+
|
44
|
+
### 信息获取
|
45
|
+
|
46
|
+
#### `api.getRuntimeConfig`
|
47
|
+
|
48
|
+
获取用户在 `modern.runtime.ts` 文件中定义的运行时配置。
|
49
|
+
|
50
|
+
- **用法**:
|
51
|
+
|
52
|
+
```ts
|
53
|
+
const config = api.getRuntimeConfig();
|
54
|
+
console.log(config.myCustomSetting);
|
55
|
+
```
|
56
|
+
|
57
|
+
:::warning
|
58
|
+
|
59
|
+
此方法返回的是用户配置的副本,修改返回值不会影响原始配置。
|
60
|
+
:::
|
61
|
+
|
62
|
+
#### `api.getHooks`
|
63
|
+
|
64
|
+
获取可用于手动触发的钩子函数。
|
65
|
+
|
66
|
+
- **类型:**
|
67
|
+
|
68
|
+
```ts
|
69
|
+
() => {
|
70
|
+
onBeforeRender: { call: (context: any) => Promise<void> };
|
71
|
+
// 其他钩子...
|
72
|
+
};
|
73
|
+
```
|
74
|
+
|
75
|
+
- **用法:**
|
76
|
+
|
77
|
+
```ts
|
78
|
+
const hooks = api.getHooks();
|
79
|
+
await hooks.onBeforeRender.call(myContext);
|
80
|
+
```
|
81
|
+
|
82
|
+
### 生命周期钩子
|
83
|
+
|
84
|
+
#### `api.onBeforeRender`
|
85
|
+
|
86
|
+
在应用渲染(包括服务器端渲染和客户端渲染)之前执行。您可以在此钩子中执行数据预取、修改渲染上下文等操作。
|
87
|
+
|
88
|
+
- **类型:**
|
89
|
+
|
90
|
+
```ts
|
91
|
+
type OnBeforeRenderFn<RuntimeContext> = (context: RuntimeContext) => Promise<void> | void;
|
92
|
+
```
|
93
|
+
`RuntimeContext` 包含当前请求的上下文信息,如请求对象、响应对象等。
|
94
|
+
|
95
|
+
- **用法:**
|
96
|
+
|
97
|
+
```ts
|
98
|
+
api.onBeforeRender(async (context) => {
|
99
|
+
const data = await fetchData(context.req);
|
100
|
+
context.data = data; // 将数据添加到上下文中
|
101
|
+
});
|
102
|
+
```
|
103
|
+
|
104
|
+
:::warning
|
105
|
+
|
106
|
+
- 此钩子在每次渲染前都会执行,因此应避免执行耗时过长的操作。
|
107
|
+
- 您可以在此钩子中修改 `context` 对象,并将修改后的 `context` 传递给后续的渲染过程。
|
108
|
+
|
109
|
+
:::
|
110
|
+
|
111
|
+
#### `api.wrapRoot`
|
112
|
+
|
113
|
+
允许您使用自定义的 React 组件包裹应用的根组件。常用于添加全局的 Provider、布局组件等。
|
114
|
+
|
115
|
+
- **类型:**
|
116
|
+
|
117
|
+
```ts
|
118
|
+
type WrapRootFn = (
|
119
|
+
App: React.ComponentType<any>
|
120
|
+
) => React.ComponentType<any>;
|
121
|
+
```
|
122
|
+
|
123
|
+
- **用法:**
|
124
|
+
|
125
|
+
```ts
|
126
|
+
api.wrapRoot((App) => {
|
127
|
+
const AppWrapper = (props) => {
|
128
|
+
return (
|
129
|
+
<MyGlobalProvider>
|
130
|
+
<Layout>
|
131
|
+
<App {...props} /> {/* 确保传递 props */}
|
132
|
+
</Layout>
|
133
|
+
</MyGlobalProvider>
|
134
|
+
);
|
135
|
+
};
|
136
|
+
return AppWrapper;
|
137
|
+
});
|
138
|
+
```
|
139
|
+
|
140
|
+
:::warning
|
141
|
+
|
142
|
+
- **务必将 `props` 传递给原始的 `App` 组件**,否则可能导致应用无法正常工作。
|
143
|
+
- `wrapRoot` 返回的组件会在每次渲染时重新创建,因此应避免在其中定义复杂的逻辑或状态。
|
144
|
+
|
145
|
+
:::
|
146
|
+
|
147
|
+
## 进阶用法
|
148
|
+
|
149
|
+
### 组合使用钩子
|
150
|
+
|
151
|
+
您可以组合使用多个钩子来实现更复杂的功能。例如,您可以使用 `onBeforeRender` 获取数据,然后使用 `wrapRoot` 将数据通过 Context 传递给整个应用:
|
152
|
+
|
153
|
+
```ts
|
154
|
+
api.onBeforeRender(async (context) => {
|
155
|
+
const data = await fetchData(context.req);
|
156
|
+
context.data = data;
|
157
|
+
});
|
158
|
+
|
159
|
+
api.wrapRoot((App) => {
|
160
|
+
return (props) => (
|
161
|
+
<DataContext.Provider value={props.data}>
|
162
|
+
<App {...props} />
|
163
|
+
</DataContext.Provider>
|
164
|
+
);
|
165
|
+
});
|
166
|
+
```
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# 生命周期
|
2
|
+
|
3
|
+
import Mermaid from '@site/src/components/Mermaid';
|
4
|
+
|
5
|
+
<Mermaid>
|
6
|
+
{`
|
7
|
+
flowchart TD
|
8
|
+
init{{"Runtime 初始化"}}
|
9
|
+
load_config(加载用户配置文件)
|
10
|
+
runtime_plugin(加载 Runtime 插件<br><sub>配置文件中注册的插件<br>CLI 插件注册的 Runtime 插件<br>插件中使用的插件</sub>)
|
11
|
+
registry_hooks(注册 Hooks 函数<br><sub>执行插件 setup 函数,注册插件中定义的 Hook, 插件 setup 中逻辑也会在这里执行</sub>)
|
12
|
+
|
13
|
+
wrapRoot(wrapRoot<br><sub>wrapRoot 中返回组件中的逻辑会在组件渲染时执行</sub>)
|
14
|
+
onBeforeRender(onBeforeRender)
|
15
|
+
|
16
|
+
init --> load_config
|
17
|
+
load_config --> runtime_plugin
|
18
|
+
runtime_plugin --> registry_hooks
|
19
|
+
registry_hooks --> wrapRoot
|
20
|
+
wrapRoot --> onBeforeRender
|
21
|
+
|
22
|
+
style init fill:#FDE68A,font-size:10px;
|
23
|
+
style load_config stroke-dasharray:5 5,fill:#86EFAC,font-size:10px;
|
24
|
+
style runtime_plugin stroke-dasharray:5 5,fill:#86EFAC,font-size:10px;
|
25
|
+
style registry_hooks stroke-dasharray:5 5,fill:#9CA3AF,font-size:10px;
|
26
|
+
style wrapRoot font-size:10px;
|
27
|
+
style onBeforeRender font-size:10px;
|
28
|
+
`}
|
29
|
+
</Mermaid>
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# 插件迁移
|
2
|
+
|
3
|
+
### 迁移背景
|
4
|
+
|
5
|
+
Modern.js 插件系统持续演进,为了提供更清晰的 API 和更强大的功能,我们对 Runtime 插件的定义和使用方式进行了优化。虽然旧版插件写法部分仍被兼容,但我们强烈建议您按照本指南进行迁移,以充分利用新版插件系统的优势。
|
6
|
+
|
7
|
+
### 迁移步骤总览
|
8
|
+
|
9
|
+
1. **更新插件类型定义**:将 `Plugin` 类型替换为 `RuntimePluginFuture`。
|
10
|
+
2. **调整 Hooks 调用方式**:从 `return hooks` 模式迁移到 `api.xxx` 直接调用。
|
11
|
+
3. **替换已变更的 API**:参照详细的 API 映射表,更新您的代码。
|
12
|
+
|
13
|
+
### 详细迁移步骤
|
14
|
+
|
15
|
+
#### 更新插件类型定义
|
16
|
+
|
17
|
+
这是迁移的第一步,也是最关键的一步。它确保您的插件能够与新版插件系统正确交互。
|
18
|
+
|
19
|
+
```typescript
|
20
|
+
// 旧版写法
|
21
|
+
import type { Plugin } from '@modern-js/runtime';
|
22
|
+
|
23
|
+
const plugin: Plugin = { ... };
|
24
|
+
|
25
|
+
// 新版写法
|
26
|
+
import type { RuntimePluginFuture } from '@modern-js/runtime';
|
27
|
+
|
28
|
+
const plugin: RuntimePluginFuture = { ... };
|
29
|
+
```
|
30
|
+
|
31
|
+
**说明:** `RuntimePluginFuture` 类型是新版插件的标准定义,它带来了更好的类型推断和更清晰的 API 结构。
|
32
|
+
|
33
|
+
#### 调整 Hooks 调用方式
|
34
|
+
|
35
|
+
新版插件系统推荐使用 `api` 对象直接调用 Hooks,这种方式更直观、更易于维护。
|
36
|
+
|
37
|
+
```typescript
|
38
|
+
// 旧版写法 (return hooks)
|
39
|
+
{
|
40
|
+
setup: () => ({
|
41
|
+
beforeRender({ req, res }) { /*...*/ }
|
42
|
+
})
|
43
|
+
}
|
44
|
+
|
45
|
+
// 新版写法 (api.xxx)
|
46
|
+
{
|
47
|
+
setup: api => {
|
48
|
+
api.onBeforeRender(({ req, res }) => { /*...*/ })
|
49
|
+
}
|
50
|
+
}
|
51
|
+
```
|
52
|
+
|
53
|
+
**说明:** `api` 对象提供了所有可用的 Hooks 和工具方法。
|
54
|
+
|
55
|
+
#### 替换已变更的 API
|
56
|
+
|
57
|
+
为了保持 API 的一致性和清晰性,我们对部分 API 的名称进行了调整。同时,`hoc` 和 `init` 这两个 Hook 已被移除,请使用新的 Hook 进行替代。下表列出了所有变更的 API 及其新旧对应关系:
|
58
|
+
|
59
|
+
| 旧版 API | 新版 API | 说明 |
|
60
|
+
| :------------ | :---------------- | :----------------------------------------------------------------------------------------------------------------------- |
|
61
|
+
| `beforeRender` | `onBeforeRender` | 在应用渲染前执行。 |
|
62
|
+
| `hoc` | `wrapRoot` | **重要变更:** 用于包裹根组件,实现高阶组件 (HOC) 的功能。请确保将 props 传递给原始组件。 |
|
63
|
+
| `init` | `onBeforeRender` | **重要变更:** 在应用渲染前执行初始化逻辑。 |
|
64
|
+
|
65
|
+
**说明:**
|
66
|
+
- `onBeforeRender` 替代了原来的 `beforeRender` 和 `init`,分别用于渲染前逻辑和初始化。
|
67
|
+
- `wrapRoot` 替代了 `hoc`,用于实现高阶组件功能,使用时务必注意 props 的传递。
|
68
|
+
|
69
|
+
**`wrapRoot` 使用示例:**
|
70
|
+
|
71
|
+
```typescript
|
72
|
+
{
|
73
|
+
setup: api => {
|
74
|
+
api.wrapRoot((App) => {
|
75
|
+
const AppWrapper = (props) => {
|
76
|
+
// 确保将 props 传递给原始组件
|
77
|
+
return <Provider value={xx}><App {...props}/></Provider>;
|
78
|
+
};
|
79
|
+
return AppWrapper;
|
80
|
+
});
|
81
|
+
}
|
82
|
+
}
|
83
|
+
```
|
84
|
+
|
85
|
+
### 常见问题解答
|
86
|
+
|
87
|
+
**Q: 迁移后,我的插件还能正常工作吗?**
|
88
|
+
|
89
|
+
A: 只要您按照本指南正确完成了所有步骤,您的插件应该能够正常工作。如果您遇到任何问题,请查阅 Modern.js 的官方文档或寻求社区支持。
|
90
|
+
|
91
|
+
**Q: 我必须立即迁移我的插件吗?**
|
92
|
+
|
93
|
+
A: 虽然旧版插件写法仍然兼容,但我们强烈建议您尽快迁移。新版插件系统提供了更好的性能和更丰富的功能,长期来看,迁移是值得的。
|
94
|
+
|
95
|
+
**Q: 我可以在哪里找到更多关于新版插件系统的信息?**
|
96
|
+
|
97
|
+
A: 请查阅 Modern.js 的官方文档,特别是关于插件系统的部分。您也可以参考其他已迁移的插件示例,了解最佳实践。
|
98
|
+
|
99
|
+
### 总结
|
100
|
+
|
101
|
+
通过这份详细的迁移指南,我们希望能够帮助您顺利地将您的 Runtime 插件迁移到 Modern.js 的新版插件系统。如果您在迁移过程中遇到任何问题,请随时向我们寻求帮助。
|
package/i18n.json
CHANGED
package/package.json
CHANGED
@@ -15,13 +15,14 @@
|
|
15
15
|
"modern",
|
16
16
|
"modern.js"
|
17
17
|
],
|
18
|
-
"version": "2.
|
18
|
+
"version": "2.66.1-alpha.0",
|
19
19
|
"publishConfig": {
|
20
20
|
"registry": "https://registry.npmjs.org/",
|
21
21
|
"access": "public"
|
22
22
|
},
|
23
23
|
"dependencies": {
|
24
|
-
"
|
24
|
+
"mermaid": "^11.4.1",
|
25
|
+
"@modern-js/sandpack-react": "2.66.0"
|
25
26
|
},
|
26
27
|
"devDependencies": {
|
27
28
|
"@rspress/shared": "1.42.0",
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import type { CSSProperties, PropsWithChildren } from 'react';
|
3
|
+
import './style.scss';
|
4
|
+
|
5
|
+
import mermaid, { type MermaidConfig } from 'mermaid';
|
6
|
+
import { useEffect, useId, useState } from 'react';
|
7
|
+
interface Props {
|
8
|
+
style?: CSSProperties;
|
9
|
+
title?: string;
|
10
|
+
config?: MermaidConfig;
|
11
|
+
}
|
12
|
+
export default function Mermaid({
|
13
|
+
style,
|
14
|
+
children,
|
15
|
+
title,
|
16
|
+
config,
|
17
|
+
}: PropsWithChildren<Props>) {
|
18
|
+
const id = useId();
|
19
|
+
const [svg, setSvg] = useState('');
|
20
|
+
const [renderError, setRenderError] = useState(false);
|
21
|
+
|
22
|
+
async function renderMermaid2SVG() {
|
23
|
+
// https://github.com/mermaid-js/mermaid/blob/1b40f552b20df4ab99a986dd58c9d254b3bfd7bc/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue#L53
|
24
|
+
const hasDarkClass = document.documentElement.classList.contains('dark');
|
25
|
+
|
26
|
+
const mermaidConfig: MermaidConfig = {
|
27
|
+
securityLevel: 'loose',
|
28
|
+
startOnLoad: false,
|
29
|
+
theme: hasDarkClass ? 'dark' : 'default',
|
30
|
+
...config,
|
31
|
+
};
|
32
|
+
|
33
|
+
try {
|
34
|
+
mermaid.initialize(mermaidConfig);
|
35
|
+
|
36
|
+
const { svg } = await mermaid.render(
|
37
|
+
id.replace(/:/g, ''),
|
38
|
+
children as string,
|
39
|
+
);
|
40
|
+
|
41
|
+
setSvg(svg);
|
42
|
+
} catch (error) {
|
43
|
+
setRenderError(true);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
useEffect(() => {
|
48
|
+
renderMermaid2SVG();
|
49
|
+
}, [children]);
|
50
|
+
return (
|
51
|
+
<>
|
52
|
+
{renderError || !svg ? null : (
|
53
|
+
<div style={style} className="modern-mermaid">
|
54
|
+
<h3>{title}</h3>
|
55
|
+
<div dangerouslySetInnerHTML={{ __html: svg }} />
|
56
|
+
</div>
|
57
|
+
)}
|
58
|
+
</>
|
59
|
+
);
|
60
|
+
}
|