@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.
Files changed (131) hide show
  1. package/docs/en/apis/app/hooks/src/app.mdx +20 -34
  2. package/docs/en/apis/app/hooks/src/modern.runtime.mdx +9 -0
  3. package/docs/en/apis/app/runtime/app/define-config.mdx +6 -0
  4. package/docs/en/community/blog/v2-release-note.mdx +1 -1
  5. package/docs/en/components/enable-micro-frontend.mdx +20 -3
  6. package/docs/en/components/micro-runtime-config.mdx +12 -13
  7. package/docs/en/components/reduck-notify.mdx +27 -0
  8. package/docs/en/configure/app/plugins.mdx +2 -2
  9. package/docs/en/configure/app/runtime/0-intro.mdx +63 -91
  10. package/docs/en/configure/app/tools/esbuild.mdx +1 -1
  11. package/docs/en/configure/app/tools/swc.mdx +1 -1
  12. package/docs/en/configure/app/usage.mdx +93 -69
  13. package/docs/en/guides/basic-features/render/_meta.json +1 -1
  14. package/docs/en/guides/basic-features/render/before-render.mdx +115 -0
  15. package/docs/en/guides/basic-features/routes.mdx +0 -95
  16. package/docs/en/guides/topic-detail/micro-frontend/c02-development.mdx +3 -5
  17. package/docs/en/guides/topic-detail/micro-frontend/c03-main-app.mdx +4 -2
  18. package/docs/en/guides/topic-detail/model/auto-actions.mdx +0 -4
  19. package/docs/en/guides/topic-detail/model/computed-state.mdx +0 -5
  20. package/docs/en/guides/topic-detail/model/define-model.mdx +0 -4
  21. package/docs/en/guides/topic-detail/model/faq.mdx +0 -5
  22. package/docs/en/guides/topic-detail/model/manage-effects.mdx +0 -5
  23. package/docs/en/guides/topic-detail/model/model-communicate.mdx +0 -5
  24. package/docs/en/guides/topic-detail/model/performance.mdx +0 -4
  25. package/docs/en/guides/topic-detail/model/quick-start.mdx +5 -7
  26. package/docs/en/guides/topic-detail/model/redux-integration.mdx +0 -4
  27. package/docs/en/guides/topic-detail/model/typescript-best-practice.mdx +0 -4
  28. package/docs/en/guides/topic-detail/model/use-model.mdx +0 -5
  29. package/docs/en/guides/topic-detail/model/use-out-of-modernjs.mdx +0 -4
  30. package/docs/en/plugin/_meta.json +8 -7
  31. package/docs/en/plugin/cli-plugins/_meta.json +1 -1
  32. package/docs/en/plugin/cli-plugins/api.mdx +617 -0
  33. package/docs/en/plugin/cli-plugins/life-cycle.mdx +139 -0
  34. package/docs/en/plugin/cli-plugins/migration.mdx +98 -0
  35. package/docs/en/plugin/introduction.mdx +119 -47
  36. package/docs/en/plugin/official/_meta.json +12 -0
  37. package/docs/en/plugin/official/cli-plugins/_meta.json +1 -0
  38. package/docs/en/plugin/official/cli-plugins.mdx +6 -0
  39. package/docs/en/plugin/official/rsbuild-plugins.mdx +3 -0
  40. package/docs/en/plugin/plugin-system.mdx +237 -0
  41. package/docs/en/plugin/runtime-plugins/_meta.json +1 -0
  42. package/docs/en/plugin/runtime-plugins/api.mdx +165 -0
  43. package/docs/en/plugin/runtime-plugins/life-cycle.mdx +29 -0
  44. package/docs/en/plugin/runtime-plugins/migration.mdx +101 -0
  45. package/docs/en/plugin/server-plugins/api.mdx +3 -0
  46. package/docs/en/plugin/server-plugins/life-cycle.mdx +3 -0
  47. package/docs/zh/apis/app/hooks/src/app.mdx +18 -26
  48. package/docs/zh/apis/app/hooks/src/modern.runtime.mdx +9 -0
  49. package/docs/zh/apis/app/runtime/app/define-config.mdx +5 -0
  50. package/docs/zh/community/blog/v2-release-note.mdx +1 -1
  51. package/docs/zh/components/enable-micro-frontend.mdx +19 -12
  52. package/docs/zh/components/micro-runtime-config.mdx +3 -3
  53. package/docs/zh/components/reduck-notify.mdx +27 -0
  54. package/docs/zh/configure/app/plugins.mdx +2 -2
  55. package/docs/zh/configure/app/runtime/0-intro.mdx +67 -86
  56. package/docs/zh/configure/app/tools/esbuild.mdx +1 -1
  57. package/docs/zh/configure/app/tools/swc.mdx +1 -1
  58. package/docs/zh/configure/app/usage.mdx +44 -21
  59. package/docs/zh/guides/basic-features/render/_meta.json +1 -1
  60. package/docs/zh/guides/basic-features/render/before-render.mdx +115 -0
  61. package/docs/zh/guides/basic-features/routes.mdx +0 -95
  62. package/docs/zh/guides/topic-detail/micro-frontend/c02-development.mdx +3 -5
  63. package/docs/zh/guides/topic-detail/micro-frontend/c03-main-app.mdx +4 -2
  64. package/docs/zh/guides/topic-detail/model/auto-actions.mdx +0 -4
  65. package/docs/zh/guides/topic-detail/model/computed-state.mdx +0 -4
  66. package/docs/zh/guides/topic-detail/model/define-model.mdx +1 -4
  67. package/docs/zh/guides/topic-detail/model/faq.mdx +0 -5
  68. package/docs/zh/guides/topic-detail/model/manage-effects.mdx +0 -4
  69. package/docs/zh/guides/topic-detail/model/model-communicate.mdx +1 -4
  70. package/docs/zh/guides/topic-detail/model/performance.mdx +0 -4
  71. package/docs/zh/guides/topic-detail/model/quick-start.mdx +7 -8
  72. package/docs/zh/guides/topic-detail/model/redux-integration.mdx +0 -4
  73. package/docs/zh/guides/topic-detail/model/typescript-best-practice.mdx +0 -4
  74. package/docs/zh/guides/topic-detail/model/use-model.mdx +0 -5
  75. package/docs/zh/guides/topic-detail/model/use-out-of-modernjs.mdx +0 -4
  76. package/docs/zh/plugin/_meta.json +8 -7
  77. package/docs/zh/plugin/cli-plugins/_meta.json +1 -1
  78. package/docs/zh/plugin/cli-plugins/api.mdx +617 -0
  79. package/docs/zh/plugin/cli-plugins/life-cycle.mdx +139 -0
  80. package/docs/zh/plugin/cli-plugins/migration.mdx +98 -0
  81. package/docs/zh/plugin/introduction.mdx +92 -20
  82. package/docs/zh/plugin/official/_meta.json +12 -0
  83. package/docs/zh/plugin/official/cli-plugins/_meta.json +1 -0
  84. package/docs/zh/plugin/official/cli-plugins.mdx +6 -0
  85. package/docs/zh/plugin/official/rsbuild-plugins.mdx +3 -0
  86. package/docs/zh/plugin/plugin-system.mdx +239 -0
  87. package/docs/zh/plugin/runtime-plugins/_meta.json +1 -0
  88. package/docs/zh/plugin/runtime-plugins/api.mdx +166 -0
  89. package/docs/zh/plugin/runtime-plugins/life-cycle.mdx +29 -0
  90. package/docs/zh/plugin/runtime-plugins/migration.mdx +101 -0
  91. package/docs/zh/plugin/server-plugins/api.mdx +3 -0
  92. package/docs/zh/plugin/server-plugins/life-cycle.mdx +3 -0
  93. package/i18n.json +4 -0
  94. package/package.json +3 -2
  95. package/src/components/Footer/index.tsx +1 -1
  96. package/src/components/Mermaid/index.tsx +60 -0
  97. package/src/components/Mermaid/style.scss +221 -0
  98. package/docs/en/plugin/cli-plugins.mdx +0 -6
  99. package/docs/en/plugin/plugin-system/_meta.json +0 -10
  100. package/docs/en/plugin/plugin-system/extend.mdx +0 -163
  101. package/docs/en/plugin/plugin-system/hook-list.mdx +0 -711
  102. package/docs/en/plugin/plugin-system/hook.mdx +0 -188
  103. package/docs/en/plugin/plugin-system/implement.mdx +0 -243
  104. package/docs/en/plugin/plugin-system/introduction.mdx +0 -95
  105. package/docs/en/plugin/plugin-system/lifecycle.mdx +0 -16
  106. package/docs/en/plugin/plugin-system/plugin-api.mdx +0 -138
  107. package/docs/en/plugin/plugin-system/relationship.mdx +0 -119
  108. package/docs/en/plugin/rsbuild-plugins.mdx +0 -3
  109. package/docs/zh/plugin/cli-plugins.mdx +0 -6
  110. package/docs/zh/plugin/plugin-system/_meta.json +0 -10
  111. package/docs/zh/plugin/plugin-system/extend.mdx +0 -163
  112. package/docs/zh/plugin/plugin-system/hook-list.mdx +0 -715
  113. package/docs/zh/plugin/plugin-system/hook.mdx +0 -173
  114. package/docs/zh/plugin/plugin-system/implement.mdx +0 -250
  115. package/docs/zh/plugin/plugin-system/introduction.mdx +0 -94
  116. package/docs/zh/plugin/plugin-system/lifecycle.mdx +0 -16
  117. package/docs/zh/plugin/plugin-system/plugin-api.mdx +0 -138
  118. package/docs/zh/plugin/plugin-system/relationship.mdx +0 -119
  119. package/docs/zh/plugin/rsbuild-plugins.mdx +0 -4
  120. /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-bff.mdx +0 -0
  121. /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-ssg.mdx +0 -0
  122. /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-swc.mdx +0 -0
  123. /package/docs/en/plugin/{cli-plugins → official/cli-plugins}/plugin-tailwind.mdx +0 -0
  124. /package/docs/en/plugin/{rsbuild-plugins → official/rsbuild-plugins}/_meta.json +0 -0
  125. /package/docs/en/plugin/{rsbuild-plugins → official/rsbuild-plugins}/plugin-esbuild.mdx +0 -0
  126. /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-bff.mdx +0 -0
  127. /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-ssg.mdx +0 -0
  128. /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-swc.mdx +0 -0
  129. /package/docs/zh/plugin/{cli-plugins → official/cli-plugins}/plugin-tailwind.mdx +0 -0
  130. /package/docs/zh/plugin/{rsbuild-plugins → official/rsbuild-plugins}/_meta.json +0 -0
  131. /package/docs/zh/plugin/{rsbuild-plugins → official/rsbuild-plugins}/plugin-esbuild.mdx +0 -0
@@ -0,0 +1,237 @@
1
+ # Plugin System
2
+
3
+ Modern.js adopts a highly extensible, plugin-based architecture, where its core functionalities and extended capabilities are implemented through plugins. The plugin system not only ensures the framework's flexibility but also provides developers with powerful customization options. This document focuses on how to write Modern.js plugins, helping you quickly get started with plugin development.
4
+
5
+ ## Core Concept: Everything is a Plugin
6
+
7
+ Modern.js adheres to the design philosophy of "everything is a plugin," modularizing the framework's various functional components and assembling and extending them through plugins. This design brings several advantages, including:
8
+
9
+ - **High Cohesion, Low Coupling:** Each functional module is independently developed, tested, and maintained, reducing system complexity.
10
+ - **Flexible and Extensible:** Users can easily customize the framework's behavior by writing or combining plugins without modifying the core code.
11
+ - **Easy to Reuse:** Plugins can be shared across projects, improving development efficiency.
12
+ - **Progressive Enhancement:** Plugins are introduced on demand, without the complexity of carrying all functionalities from the start.
13
+
14
+ ## Plugin Types and Use Cases
15
+
16
+ Modern.js provides three main plugin types, corresponding to different stages of application development:
17
+
18
+ **CLI Plugins:**
19
+ - **Active Stage:** Build time (when executing the `modern` command).
20
+ - **Typical Scenarios:**
21
+ - Extending command-line tools.
22
+ - Modifying build configurations.
23
+ - Listening for file changes.
24
+ - Controlling the build process.
25
+ - **Configuration Method:** The `plugins` field in `modern.config.ts`.
26
+
27
+ **Runtime Plugins:**
28
+ - **Active Stage:** Application runtime (browser/Node.js environment).
29
+ - **Typical Scenarios:**
30
+ - Initializing global state or services.
31
+ - Encapsulating React Higher-Order Components (HOCs).
32
+ - Intercepting or modifying routing behavior.
33
+ - Controlling the rendering process.
34
+ - **Configuration Method:** The `plugins` field in `src/modern.runtime.ts`.
35
+
36
+ {/* **Server Plugins:**
37
+ - **Active Stage:** Server request processing stage.
38
+ - **Typical Scenarios:**
39
+ - Adding custom middleware.
40
+ - Extending server-side APIs.
41
+ - Customizing SSR logic.
42
+ - Integrating with backend frameworks.
43
+ - **Configuration Method:** The `plugins` field in `server/modern.server.ts`. */}
44
+
45
+ ## Plugin Structure
46
+
47
+ A typical Modern.js plugin consists of the following key parts:
48
+
49
+ ```ts
50
+ import type { Plugin } from '@modern-js/plugin-v2';
51
+
52
+ const myPlugin: Plugin = {
53
+ name: 'my-awesome-plugin', // The unique identifier of the plugin (required)
54
+
55
+ // Plugin dependencies and execution order (optional)
56
+ pre: [], // List of plugin names to execute before this plugin, defaults to an empty array
57
+ post: [], // List of plugin names to execute after this plugin, defaults to an empty array
58
+ required: [],// List of required plugins; if a dependent plugin is not registered, an error will be thrown, defaults to an empty array
59
+ usePlugins: [], // List of plugin instances used internally, defaults to an empty array
60
+
61
+ // Register new Hooks (optional)
62
+ registryHook: {},
63
+
64
+ // The entry function of the plugin (required)
65
+ setup(api) {
66
+ // The core logic of the plugin, calling plugin APIs through the api object
67
+ api.modifyWebpackConfig(config => { /* ... */ });
68
+ api.onPrepare(() => { /* ... */ });
69
+ // ... Other API calls
70
+ },
71
+ };
72
+
73
+ export default myPlugin;
74
+ ```
75
+
76
+ **Field Descriptions:**
77
+
78
+ ##### `name`
79
+
80
+ - Type: `string`
81
+ - Description: Identifies the name of the plugin. This name must be unique within the plugin system; otherwise, the plugin will fail to load.
82
+
83
+ :::info
84
+ The plugin names declared in `pre`, `post`, and `required` refer to this `name` field.
85
+ :::
86
+
87
+ ##### `setup`
88
+
89
+ - Type: `(api: PluginAPI) => MaybePromise<void>`
90
+ - Description: The main entry point for the plugin's logic.
91
+
92
+ ###### `api`
93
+
94
+ - Type: `PluginAPI`
95
+ - Description: The plugin's API, containing the Hooks and utility functions supported by the plugin.
96
+
97
+ ##### `pre`
98
+
99
+ - Type: `string[]`
100
+ - Description: Used to insert the plugin execution order. Plugins declared in `pre` will be executed before this plugin.
101
+
102
+ ##### `post`
103
+
104
+ - Type: `string[]`
105
+ - Description: Used to determine the plugin execution order. Plugins declared in `post` will be executed after this plugin.
106
+
107
+ ##### `required`
108
+
109
+ - Type: `string[]`
110
+ - Description: Other plugins that this plugin depends on. Before running, it will check if the dependent plugins are registered.
111
+
112
+ :::info
113
+ If unregistered plugin names are configured in `pre` or `post`, these plugin names will be **automatically ignored** and will not affect the execution of other plugins.
114
+
115
+ If you need to explicitly declare that the plugins that the current plugin depends on must exist, you need to use the `required` field.
116
+ :::
117
+
118
+ ##### `usePlugins`
119
+
120
+ - Type: `Plugin`
121
+ - Description: Actively register other plugins of the same type within the plugin.
122
+
123
+ :::info
124
+ Plugins declared in `usePlugins` are executed before the current plugin by default. To execute them after, use the `post` declaration.
125
+ :::
126
+ ##### `registryHooks`
127
+
128
+ - Type: `Record<string, PluginHook<(...args: any[]) => any>>`
129
+ - Description: Extend the currently supported Hook functions to implement custom functionality.
130
+
131
+ ## Plugin Hook Model
132
+
133
+ The core of the Modern.js plugin system is its Hook model, which defines the communication mechanism between plugins. Modern.js mainly provides two types of Hooks:
134
+
135
+ ### Async Hook
136
+
137
+ - **Characteristics:**
138
+ - Hook functions are executed asynchronously, supporting `async/await`.
139
+ - The return value of the previous Hook function is passed as the first argument to the next Hook function.
140
+ - Finally returns the return value of the last Hook function.
141
+ - **Use Cases:** Scenarios involving asynchronous operations (such as network requests, file reading/writing, etc.).
142
+ - **Creation Method:** Created using `createAsyncHook`.
143
+
144
+ Example:
145
+
146
+ ```ts
147
+ // Define Hooks
148
+ import { createAsyncHook } from '@modern-js/plugin-v2';
149
+
150
+ export type AfterPrepareFn = () => Promise<void> | void;
151
+ export const onAfterPrepare = createAsyncHook<AfterPrepareFn>();
152
+
153
+ // Register Hooks in the plugin
154
+ const myPlugin = () => ({
155
+ name: "my-plugin",
156
+ registryHooks: {
157
+ onAfterPrepare,
158
+ },
159
+ setup: (api) => {
160
+ api.onPrepare(async () => {
161
+ // Use the registered Hooks in the plugin
162
+ const hooks = api.getHooks();
163
+ await hooks.onAfterPrepare.call();
164
+ });
165
+ }
166
+ });
167
+
168
+ // Use Hook in other plugins
169
+ const myPlugin2 = () => ({
170
+ name: "my-plugin-2",
171
+ setup: (api) => {
172
+ api.onAfterPrepare(async () => {
173
+ // TODO
174
+ });
175
+ }
176
+ })
177
+ ```
178
+
179
+ ### Sync Hook (Synchronous Hook)
180
+
181
+ - **Characteristics:**
182
+ - Hook functions are executed synchronously.
183
+ - The return value of the previous Hook function is passed as the first argument to the next Hook function.
184
+ - Finally returns the return value of the last Hook function.
185
+ - **Use Cases:** Scenarios where data needs to be modified synchronously (such as modifying configurations, routes, etc.).
186
+ - **Creation Method:** Created using `createSyncHook`.
187
+
188
+ Example:
189
+
190
+ ```ts
191
+ // Define Hooks
192
+ import { createSyncHook } from '@modern-js/plugin-v2';
193
+
194
+ type RouteObject = {/** TODO **/};
195
+ const modifyRoutes = createSyncHook<(routes: RouteObject[]) => RouteObject[]>();
196
+
197
+ // Register Hooks in the plugin
198
+ const myPlugin = () => ({
199
+ name: "my-plugin",
200
+ registryHooks: {
201
+ modifyRoutes,
202
+ },
203
+ setup: (api) => {
204
+ api.onPrepare(async () => {
205
+ const routes = {};
206
+ // Use registered Hooks in the plugin
207
+ const hooks = api.getHooks();
208
+ const routesResult = hooks.modifyRoutes.call(routes);
209
+ });
210
+ }
211
+ });
212
+
213
+ // Other plugins use Hooks
214
+ const myPlugin2 = () => ({
215
+ name: "my-plugin",
216
+ setup: (api) => {
217
+ api.modifyRoutes(async (routes) => {
218
+ // Modify routes
219
+ return routes;
220
+ });
221
+ }
222
+ });
223
+ ```
224
+
225
+ ## Plugin Development Best Practices
226
+
227
+ - **Single Responsibility:** Each plugin should focus on implementing a specific, cohesive function. Avoid creating plugins with complex functionalities and unclear responsibilities.
228
+ - **Naming Conventions:** Plugin names should be clear, concise, and follow certain naming conventions (such as `plugin-xxx` or `@scope/plugin-xxx`).
229
+ - **Type Safety:** Make full use of TypeScript's type system to ensure the type safety of the plugin API and reduce runtime errors.
230
+ - **Comprehensive Documentation:** Write clear documentation for the plugin, including API descriptions, usage examples, configuration explanations, and change logs.
231
+ - **Thorough Testing:** Conduct unit tests and integration tests on the plugin to ensure its stability, reliability, and compatibility in various scenarios.
232
+ - **Minimize Side Effects:** Plugins should minimize modifications to the external environment (such as global variables, file systems, etc.) to maintain the plugin's independence and portability.
233
+ - **Error Handling:** Plugins should properly handle potential errors to prevent the entire application from crashing due to plugin exceptions.
234
+ - **Performance Optimization:** Pay attention to the performance impact of the plugin, avoid unnecessary calculations and resource consumption, especially in loops or frequently called Hooks.
235
+ - **Version Control:** Follow Semantic Versioning (SemVer) to ensure the backward compatibility of the plugin and facilitate user upgrades.
236
+
237
+ Following these best practices can help you develop high-quality, easy-to-maintain, and easy-to-use Modern.js plugins.
@@ -0,0 +1 @@
1
+ ["api", "life-cycle", "migration"]
@@ -0,0 +1,165 @@
1
+ # Plugin API
2
+
3
+ Modern.js's Runtime Plugins allow you to extend and modify the behavior of your application during its React code execution. With Runtime Plugins, you can easily perform initialization tasks, implement React Higher-Order Component (HOC) wrapping, and more.
4
+
5
+ ## Plugin Structure
6
+
7
+ A typical Runtime Plugin looks like this:
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
+ // Use the api to register hooks
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`: A unique identifier for the plugin.
35
+ - `setup`: The main logic of the plugin, which receives an `api` object as a parameter. This `api` object is used to register hooks.
36
+
37
+ ## API Overview
38
+
39
+ The Runtime Plugin API is primarily divided into the following categories:
40
+
41
+ - **Information Retrieval**: Getting runtime configuration and hook functions.
42
+ - **Lifecycle Hooks**: Executing custom logic at different stages of the application's rendering process.
43
+
44
+ ### Information Retrieval
45
+
46
+ #### `api.getRuntimeConfig`
47
+
48
+ Gets the runtime configuration defined by the user in the `modern.runtime.ts` file.
49
+
50
+ - **Usage**:
51
+
52
+ ```ts
53
+ const config = api.getRuntimeConfig();
54
+ console.log(config.myCustomSetting);
55
+ ```
56
+
57
+ :::warning
58
+
59
+ This method returns a *copy* of the user's configuration. Modifying the returned value will not affect the original configuration.
60
+ :::
61
+
62
+ #### `api.getHooks`
63
+
64
+ Gets the hook functions that can be triggered manually.
65
+
66
+ - **Type:**
67
+
68
+ ```ts
69
+ () => {
70
+ onBeforeRender: { call: (context: any) => Promise<void> };
71
+ // Other hooks...
72
+ };
73
+ ```
74
+
75
+ - **Usage:**
76
+
77
+ ```ts
78
+ const hooks = api.getHooks();
79
+ await hooks.onBeforeRender.call(myContext);
80
+ ```
81
+
82
+ ### Lifecycle Hooks
83
+
84
+ #### `api.onBeforeRender`
85
+
86
+ Executes before the application renders (including both server-side rendering and client-side rendering). You can use this hook to perform data prefetching, modify the rendering context, etc.
87
+
88
+ - **Type:**
89
+
90
+ ```ts
91
+ type OnBeforeRenderFn<RuntimeContext> = (context: RuntimeContext) => Promise<void> | void;
92
+ ```
93
+ `RuntimeContext` contains contextual information about the current request, such as the request object, response object, etc.
94
+
95
+ - **Usage:**
96
+
97
+ ```ts
98
+ api.onBeforeRender(async (context) => {
99
+ const data = await fetchData(context.req);
100
+ context.data = data; // Add the data to the context
101
+ });
102
+ ```
103
+
104
+ :::warning
105
+
106
+ - This hook executes before *every* render, so avoid performing long-running operations.
107
+ - You can modify the `context` object in this hook, and the modified `context` will be passed to subsequent rendering processes.
108
+
109
+ :::
110
+
111
+ #### `api.wrapRoot`
112
+
113
+ Allows you to wrap the application's root component with a custom React component. This is commonly used to add global Providers, layout components, etc.
114
+
115
+ - **Type:**
116
+
117
+ ```ts
118
+ type WrapRootFn = (
119
+ App: React.ComponentType<any>
120
+ ) => React.ComponentType<any>;
121
+ ```
122
+
123
+ - **Usage:**
124
+
125
+ ```ts
126
+ api.wrapRoot((App) => {
127
+ const AppWrapper = (props) => {
128
+ return (
129
+ <MyGlobalProvider>
130
+ <Layout>
131
+ <App {...props} /> {/* Make sure to pass props */}
132
+ </Layout>
133
+ </MyGlobalProvider>
134
+ );
135
+ };
136
+ return AppWrapper;
137
+ });
138
+ ```
139
+ :::warning
140
+
141
+ - **It is crucial to pass the `props` to the original `App` component**, otherwise, the application may not function correctly.
142
+ - The component returned by `wrapRoot` is recreated on every render, so avoid defining complex logic or state within it.
143
+
144
+ :::
145
+
146
+ ## Advanced Usage
147
+
148
+ ### Combining Hooks
149
+
150
+ You can combine multiple hooks to implement more complex functionality. For example, you can use `onBeforeRender` to fetch data and then use `wrapRoot` to pass the data to the entire application via Context:
151
+
152
+ ```ts
153
+ api.onBeforeRender(async (context) => {
154
+ const data = await fetchData(context.req);
155
+ context.data = data;
156
+ });
157
+
158
+ api.wrapRoot((App) => {
159
+ return (props) => (
160
+ <DataContext.Provider value={props.data}>
161
+ <App {...props} />
162
+ </DataContext.Provider>
163
+ );
164
+ });
165
+ ```
@@ -0,0 +1,29 @@
1
+ # Life Cycle
2
+
3
+ import Mermaid from '@site/src/components/Mermaid';
4
+
5
+ <Mermaid>
6
+ {`
7
+ flowchart TD
8
+ init{{"Runtime Initialization"}}
9
+ load_config(Load User Configuration File)
10
+ runtime_plugin(Load Runtime Plugins<br><sub>Plugins registered in the configuration file<br>Runtime plugins registered by CLI<br>Plugins used within plugins</sub>)
11
+ registry_hooks(Register Hooks Functions<br><sub>Execute the plugin setup function, register hooks defined in the plugin, and the logic in the plugin setup will also be executed here</sub>)
12
+
13
+ wrapRoot(wrapRoot<br><sub>The logic returned in wrapRoot will be executed when the component is rendered</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
+ # Plugin Migration
2
+
3
+ ### Migration Background
4
+
5
+ The Modern.js plugin system is constantly evolving. To provide a clearer API and more powerful features, we've optimized the definition and usage of Runtime plugins. While the old plugin syntax is still partially compatible, we strongly recommend migrating according to this guide to take full advantage of the new plugin system.
6
+
7
+ ### Migration Steps Overview
8
+
9
+ 1. **Update Plugin Type Definition:** Replace the `Plugin` type with `RuntimePluginFuture`.
10
+ 2. **Adjust Hook Invocation:** Migrate from the `return hooks` pattern to direct `api.xxx` calls.
11
+ 3. **Replace Changed APIs:** Refer to the detailed API mapping table and update your code.
12
+
13
+ ### Detailed Migration Steps
14
+
15
+ #### Update Plugin Type Definition
16
+
17
+ This is the first and most crucial step. It ensures that your plugin interacts correctly with the new plugin system.
18
+
19
+ ```typescript
20
+ // Old Syntax
21
+ import type { Plugin } from '@modern-js/runtime';
22
+
23
+ const plugin: Plugin = { ... };
24
+
25
+ // New Syntax
26
+ import type { RuntimePluginFuture } from '@modern-js/runtime';
27
+
28
+ const plugin: RuntimePluginFuture = { ... };
29
+ ```
30
+
31
+ **Explanation:** The `RuntimePluginFuture` type is the standard definition for new plugins. It provides better type inference and a clearer API structure.
32
+
33
+ #### Adjust Hook Invocation
34
+
35
+ The new plugin system recommends using the `api` object to directly call Hooks. This approach is more intuitive and easier to maintain.
36
+
37
+ ```typescript
38
+ // Old Syntax (return hooks)
39
+ {
40
+ setup: () => ({
41
+ beforeRender({ req, res }) { /*...*/ }
42
+ })
43
+ }
44
+
45
+ // New Syntax (api.xxx)
46
+ {
47
+ setup: api => {
48
+ api.onBeforeRender(({ req, res }) => { /*...*/ })
49
+ }
50
+ }
51
+ ```
52
+
53
+ **Explanation:** The `api` object provides all available Hooks and utility methods.
54
+
55
+ #### Replace Changed APIs
56
+
57
+ To maintain API consistency and clarity, we've adjusted the names of some APIs. Additionally, the `hoc` and `init` Hooks have been removed. Please use the new Hooks as replacements. The table below lists all changed APIs and their old and new counterparts:
58
+
59
+ | Old API | New API | Description |
60
+ | :------------ | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
61
+ | `beforeRender` | `onBeforeRender` | Executed before application rendering. |
62
+ | `hoc` | `wrapRoot` | **Important Change:** Used to wrap the root component, achieving the functionality of a Higher-Order Component (HOC). Make sure to pass props to the original component. |
63
+ | `init` | `onBeforeRender` | **Important Change:** Execute initialization logic before application rendering. This replaces the previous `init` hook. Use `onBeforeRender` to perform any setup or initialization tasks that were previously done in `init`. This provides a single, consistent point for pre-rendering logic. |
64
+
65
+ **Explanation:**
66
+ - `onBeforeRender` replaces both the original `beforeRender` and `init`, used for pre-rendering logic and initialization, respectively.
67
+ - `wrapRoot` replaces `hoc` and is used to implement higher-order component functionality. It's crucial to pass props correctly when using `wrapRoot`.
68
+
69
+ **`wrapRoot` Usage Example:**
70
+
71
+ ```typescript
72
+ {
73
+ setup: api => {
74
+ api.wrapRoot((App) => {
75
+ const AppWrapper = (props) => {
76
+ // Ensure props are passed to the original component
77
+ return <Provider value={xx}><App {...props}/></Provider>;
78
+ };
79
+ return AppWrapper;
80
+ });
81
+ }
82
+ }
83
+ ```
84
+
85
+ ### Frequently Asked Questions
86
+
87
+ **Q: Will my plugin still work correctly after migration?**
88
+
89
+ A: As long as you've correctly completed all the steps in this guide, your plugin should function properly. If you encounter any issues, please refer to the official Modern.js documentation or seek community support.
90
+
91
+ **Q: Do I have to migrate my plugin immediately?**
92
+
93
+ A: While the old plugin syntax remains partially compatible, we strongly recommend migrating as soon as possible. The new plugin system offers improved performance and richer functionality, making migration worthwhile in the long run.
94
+
95
+ **Q: Where can I find more information about the new plugin system?**
96
+
97
+ A: Please consult the official Modern.js documentation, especially the section on the plugin system. You can also refer to examples of other migrated plugins to understand best practices.
98
+
99
+ ### Summary
100
+
101
+ With this detailed migration guide, we hope to help you smoothly transition your Runtime plugins to the new Modern.js plugin system. If you encounter any problems during the migration process, please don't hesitate to ask for assistance.
@@ -0,0 +1,3 @@
1
+ # Plugin API
2
+
3
+ Comming soon...
@@ -0,0 +1,3 @@
1
+ # Life Cycle
2
+
3
+ Comming soon...
@@ -2,6 +2,7 @@
2
2
  title: App.[tj]sx
3
3
  sidebar_position: 1
4
4
  ---
5
+
5
6
  # App.[tj]sx
6
7
 
7
8
  应用使用[自控路由](/guides/concept/entries.html#自控式路由)时的入口标识符。
@@ -9,35 +10,26 @@ sidebar_position: 1
9
10
  `App.[tj]sx` 并不是实际的应用入口,Modern.js 会自动生成真正的构建打包的入口文件, 内容大致如下:
10
11
 
11
12
  ```js
12
- import React from 'react';
13
- import ReactDOM from 'react-dom/client';
14
- import { createApp, bootstrap } from '@modern-js/runtime';
15
- // App.[jt]sx
13
+ // runtime-global-context
14
+ import { setGlobalContext } from '@modern-js/runtime/context';
16
15
  import App from '@_modern_js_src/App';
17
- // runtime plugin
18
- import { router } from '@modern-js/runtime/plugins';
19
-
20
- const IS_BROWSER = typeof window !== 'undefined' && window.name !== 'nodejs';
21
- const MOUNT_ID = 'root';
22
-
23
- let AppWrapper = null;
24
-
25
- function render() {
26
- AppWrapper = createApp({
27
- plugins: [
28
- router({...{"serverBase":["/"]}, ...App.config?.router}),
29
- ]
30
- })(App)
31
- if (IS_BROWSER) {
32
- bootstrap(AppWrapper, MOUNT_ID, null, ReactDOM);
33
- }
34
- return AppWrapper
35
- }
36
-
37
- AppWrapper = render();
38
- export default AppWrapper;
16
+
17
+ setGlobalContext({
18
+ App,
19
+ });
20
+
21
+ // index.tsx
22
+ import './runtime-global-context';
23
+ import { createRoot } from '@modern-js/runtime/react';
24
+ import { render } from '@modern-js/runtime/browser';
25
+
26
+ const ModernRoot = createRoot();
27
+
28
+ render(<ModernRoot />, 'root');
39
29
  ```
40
30
 
31
+ `createRoot` 执行时,会去获取注册的 Globa App,生成真实的 React 组件。
32
+
41
33
  :::note
42
34
  在多入口的场景下,每个入口都可以拥有独立的 `App.[jt]sx`,详见[入口](/guides/concept/entries)。
43
35
 
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: modern.runtime.[tj]s
3
+ sidebar_position: 4
4
+ ---
5
+ # modern.runtime.[tj]s
6
+
7
+ Modern.js Runtime 配置文件, 通过该文件可以对当前项目的 Runtime 能力进行个性化配置。
8
+
9
+ 了解配置的具体用法,请参考 [Runtime 配置](/configure/app/runtime/0-intro.html)。
@@ -4,6 +4,11 @@ title: defineConfig
4
4
  ---
5
5
  # defineConfig
6
6
 
7
+ :::warning
8
+
9
+ 该 API 即将废弃,推荐使用 `src/modern.runtime.ts` 定义 Runtime 配置,同时支持静态配置和动态配置,使用姿势插件[Runtime 配置](/configure/app/runtime/0-intro.html)
10
+ :::
11
+
7
12
  用于动态配置应用。
8
13
 
9
14
  ## 使用姿势
@@ -132,7 +132,7 @@ Modern.js 可以划分为三个核心部分:**CLI 工具、服务端和运行
132
132
 
133
133
  在字节跳动内部,我们借助这些插件 API,结合公司内的基建和平台,封装出内部的企业级框架。如果你需要对 Modern.js 框架进行深度定制,也可以借助这些插件 API 来完成。
134
134
 
135
- > 如果你对 Modern.js 的插件系统感兴趣,请阅读 [「Modern.js - 自定义插件」](https://modernjs.dev/plugin/plugin-system/introduction.html)文档。
135
+ > 如果你对 Modern.js 的插件系统感兴趣,请阅读 [「Modern.js - 自定义插件」](https://modernjs.dev/plugin/plugin-system.html)文档。
136
136
 
137
137
  ### 嵌套路由
138
138
 
@@ -1,23 +1,30 @@
1
- ```js title="modern.config.ts"
1
+ ```ts title="modern.config.ts"
2
2
  import { appTools, defineConfig } from '@modern-js/app-tools';
3
3
  import { garfishPlugin } from '@modern-js/plugin-garfish';
4
4
 
5
5
  export default defineConfig({
6
6
  runtime: {
7
7
  router: true,
8
- masterApp: {
9
- apps: [{
10
- name: 'Table',
11
- entry: 'http://localhost:8081',
12
- // activeWhen: '/table'
13
- }, {
14
- name: 'Dashboard',
15
- entry: 'http://localhost:8082'
16
- // activeWhen: '/dashboard'
17
- }]
18
- },
19
8
  },
20
9
  plugins: [appTools(), garfishPlugin()],
21
10
  });
22
11
 
23
12
  ```
13
+
14
+ ```ts title="src/modern.runtime.ts"
15
+ import { defineRuntimeConfig } from '@modern-js/runtime';
16
+
17
+ export default defineRuntimeConfig({
18
+ masterApp: {
19
+ apps: [{
20
+ name: 'Table',
21
+ entry: 'http://localhost:8081',
22
+ // activeWhen: '/table'
23
+ }, {
24
+ name: 'Dashboard',
25
+ entry: 'http://localhost:8082'
26
+ // activeWhen: '/dashboard'
27
+ }]
28
+ },
29
+ });
30
+ ```