@modern-js/main-doc 2.44.0 → 2.46.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/components/stream-ssr-performance.mdx +0 -0
- package/docs/en/configure/app/server/ssr.mdx +2 -0
- package/docs/en/guides/advanced-features/rspack-start.mdx +62 -14
- package/docs/en/guides/advanced-features/ssr/stream.mdx +12 -0
- package/docs/en/guides/basic-features/data/data-fetch.mdx +45 -0
- package/docs/en/guides/basic-features/html.mdx +0 -2
- package/docs/en/guides/get-started/glossary.mdx +6 -0
- package/docs/zh/components/stream-ssr-performance.mdx +0 -0
- package/docs/zh/configure/app/server/ssr.mdx +2 -0
- package/docs/zh/guides/advanced-features/rspack-start.mdx +62 -15
- package/docs/zh/guides/advanced-features/ssr/stream.mdx +12 -0
- package/docs/zh/guides/basic-features/css-modules.mdx +1 -1
- package/docs/zh/guides/basic-features/data/data-fetch.mdx +75 -0
- package/docs/zh/guides/basic-features/html.mdx +0 -2
- package/docs/zh/guides/get-started/glossary.mdx +6 -0
- package/docs/zh/guides/topic-detail/generator/plugin/api/onForged.md +1 -1
- package/package.json +7 -7
- package/docs/en/configure/app/tools/inspector.mdx +0 -9
- package/docs/zh/configure/app/tools/inspector.mdx +0 -9
File without changes
|
@@ -31,6 +31,7 @@ When the value type is `Object`, the following properties can be configured:
|
|
31
31
|
- `disablePrerender`: `boolean = fasle`, To ensure compatibility with the old data request method (`useLoader`), by default, Modern.js performs pre-rendering of components.
|
32
32
|
However, if developers want to reduce one rendering when there is no use of the useLoader API in your project, you can set the configuration `disablePrerender=true`.
|
33
33
|
- `unsafeHeaders`: `string[] = []`, For safety reasons, Modern.js does not add excessive content to SSR_DATA. Developers can use this configuration to specify the headers that need to be injected.
|
34
|
+
- `scriptLoading`: `'defer' | 'blocking' | 'module' | 'async'`, The configuration is the same as [html.scriptLoading](/configure/app/html/script-loading), supporting SSR injected script set to `async` loading. The priority is `ssr.scriptLoading` > `html.scriptLoading`.
|
34
35
|
|
35
36
|
```ts title="modern.config.ts"
|
36
37
|
export default defineConfig({
|
@@ -40,6 +41,7 @@ export default defineConfig({
|
|
40
41
|
mode: 'stream',
|
41
42
|
inlineScript: false,
|
42
43
|
unsafeHeaders: ['User-Agent'],
|
44
|
+
scriptLoading: 'async',
|
43
45
|
},
|
44
46
|
},
|
45
47
|
});
|
@@ -25,27 +25,18 @@ After the project is created, you can experience the project by running `pnpm ru
|
|
25
25
|
:::tip
|
26
26
|
When using Rspack as the bundler, the following Features are temporarily unavailable as some of the capabilities are still under development and we will provide support in the future.
|
27
27
|
|
28
|
-
- Storybook Devtool
|
29
28
|
- The usage of [useLoader](/guides/basic-features/data/data-fetch.html) in Client Side Rendering
|
30
29
|
|
31
30
|
:::
|
32
31
|
|
33
32
|
## Enable Rspack build
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
```bash
|
38
|
-
$ pnpm run new
|
39
|
-
? Please select the operation you want: Enable features
|
40
|
-
? Please select the feature name: Enable Rspack Build
|
41
|
-
```
|
42
|
-
|
43
|
-
After executing the command, enable the Rspack build in `modern.config.ts`:
|
34
|
+
Since Modern.js MAJOR_VERSION.46.0, you can enable Rspack build by add the following configuration in `modern.config.ts`:
|
44
35
|
|
45
36
|
```diff title=modern.config.ts
|
46
37
|
import { appTools, defineConfig } from '@modern-js/app-tools';
|
47
38
|
|
48
|
-
|
39
|
+
export default defineConfig({
|
49
40
|
plugins: [
|
50
41
|
appTools({
|
51
42
|
+ bundler: 'experimental-rspack',
|
@@ -54,6 +45,10 @@ import { appTools, defineConfig } from '@modern-js/app-tools';
|
|
54
45
|
});
|
55
46
|
```
|
56
47
|
|
48
|
+
:::tip
|
49
|
+
If your current version is lower than MAJOR_VERSION.46.0, you can upgrade by executing `npx modern upgrade`.
|
50
|
+
:::
|
51
|
+
|
57
52
|
import RspackPrecautions from '@modern-js/builder-doc/docs/en/shared/rspackPrecautions.md';
|
58
53
|
|
59
54
|
<RspackPrecautions />
|
@@ -62,15 +57,69 @@ import RspackPrecautions from '@modern-js/builder-doc/docs/en/shared/rspackPreca
|
|
62
57
|
|
63
58
|
After enabling Rspack building capability, further configuration migration is needed by referring to the [Configuration Differences](https://modernjs.dev/builder/en/guide/advanced/rspack-start.html#migrating-from-webpack-to-rspack).
|
64
59
|
|
60
|
+
In Modern.js, the [tools.webpack](/configure/app/tools/webpack) and [tools.webpackChain](/configure/app/tools/webpack-chain) configurations only take effect in webpack mode, after turning on the Rspack build, you can modify it to [tools.rspack](/configure/app/tools/rspack) and [tools.bundlerChain](/configure/app/tools/bundler-chain).
|
61
|
+
|
62
|
+
```diff
|
63
|
+
export default {
|
64
|
+
tools: {
|
65
|
+
- webppack: (config, { env }) => {
|
66
|
+
+ rspack: (config, { env }) => {
|
67
|
+
if (env === 'development') {
|
68
|
+
config.devtool = 'cheap-module-eval-source-map';
|
69
|
+
}
|
70
|
+
return config;
|
71
|
+
},
|
72
|
+
- webpackChain: (chain, { env }) => {
|
73
|
+
+ bundlerChain: (chain, { env }) => {
|
74
|
+
if (env === 'development') {
|
75
|
+
chain.devtool('cheap-module-eval-source-map');
|
76
|
+
}
|
77
|
+
},
|
78
|
+
},
|
79
|
+
};
|
80
|
+
```
|
81
|
+
|
82
|
+
:::tip
|
83
|
+
After turning on the Rspack build capability, there are currently a small number of configurations that are not supported in Rspack, such as [source.moduleScopes](/configure/app/source/module-scopes), [security.sri](/configure/app/security/sri) etc.
|
84
|
+
|
85
|
+
For unsupported configurations, we have marked `Bundler: only support webpack` or `Bundler: only support Rspack` in the document. Please refer to the specific configuration introduction.
|
86
|
+
:::
|
87
|
+
|
88
|
+
## Modify transpile configuration
|
89
|
+
|
90
|
+
Modern.js uses Rspack [builtin:swc-loader](https://www.rspack.dev/guide/builtin-swc-loader.html) for code translation in Rspack mode.
|
91
|
+
|
92
|
+
Modern.js has provided a more convenient configuration for the common configuration of `builtin:swc-loader`, such as: configuring the component library to import it on demand through [source.transformImport](/configure/app/source/transform-import). If you have custom configuration requirements for `builtin:swc-loader`, you can refer to the following code:
|
93
|
+
|
94
|
+
```ts
|
95
|
+
export default {
|
96
|
+
tools: {
|
97
|
+
bundlerChain: (chain, { CHAIN_ID }) => {
|
98
|
+
chain.module
|
99
|
+
.rule(CHAIN_ID.RULE.JS)
|
100
|
+
.use(CHAIN_ID.USE.SWC)
|
101
|
+
.tap(options => {
|
102
|
+
options.xxx = '';
|
103
|
+
return options;
|
104
|
+
});
|
105
|
+
},
|
106
|
+
}
|
107
|
+
};
|
108
|
+
```
|
109
|
+
|
110
|
+
:::tip
|
111
|
+
When Rspack build is enabled, `babel-loader` is not enabled by default. If you need to add some babel plugins, you can configure it through [tools.babel](/configure/app/tools/babel). This will generate additional compilation overhead and slow down the Rspack build speed to a certain extent.
|
112
|
+
:::
|
113
|
+
|
65
114
|
## The relationship between Rspack and Modern.js versions
|
66
115
|
|
67
116
|
Usually, the latest version of Rspack will be integrated into Modern.js. You can update the Modern.js-related dependencies and built-in Rspack to the latest version by using `npx modern upgrade` in your project.
|
68
117
|
|
69
118
|
However, Modern.js uses a locked version dependency method (non-automatic upgrade) for Rspack. Due to differences in release cycles, the version of Rspack integrated into Modern.js may be behind the latest version of Rspack.
|
70
119
|
|
71
|
-
When Rspack is enabled for building through dev / build, the current version of Rspack used in the framework will be printed automatically:
|
120
|
+
When Rspack is enabled for building through dev / build, the current version of Rspack used in the framework will be printed automatically when debugging mode is turned on:
|
72
121
|
|
73
|
-

|
74
123
|
|
75
124
|
### Override the Built-in Rspack Version
|
76
125
|
|
@@ -84,7 +133,6 @@ For example, if you are using pnpm, you can update the Rspack version with `over
|
|
84
133
|
"overrides": {
|
85
134
|
"@rspack/core": "nightly",
|
86
135
|
"@rspack/plugin-react-refresh": "nightly",
|
87
|
-
"@rspack/plugin-html": "nightly"
|
88
136
|
}
|
89
137
|
}
|
90
138
|
}
|
@@ -228,9 +228,21 @@ function ErrorElement() {
|
|
228
228
|
}
|
229
229
|
```
|
230
230
|
|
231
|
+
## Waiting for all content to load for spiders
|
232
|
+
|
233
|
+
Streaming offers a better user experience because the user can see the content as it becomes available.
|
234
|
+
|
235
|
+
However, when a spider visits your page, you might want to let all of the content load first and then produce the final HTML output instead of revealing it progressively.
|
236
|
+
|
237
|
+
Modern.js uses [isbot](https://www.npmjs.com/package/isbot) to examine the user-agent of requests, determining whether they come from a crawler.
|
238
|
+
|
231
239
|
:::info More
|
232
240
|
|
233
241
|
1. [Deferred Data](https://reactrouter.com/en/main/guides/deferred)
|
234
242
|
2. [New Suspense SSR Architecture in React 18](https://github.com/reactwg/react-18/discussions/37)
|
235
243
|
|
236
244
|
:::
|
245
|
+
|
246
|
+
import StreamSSRPerformance from '@site-docs/components/stream-ssr-performance';
|
247
|
+
|
248
|
+
<StreamSSRPerformance />
|
@@ -306,6 +306,10 @@ If you define the [`shouldRevalidate`](#/shouldrevalidate) function on the route
|
|
306
306
|
|
307
307
|
### `shouldRevalidate`
|
308
308
|
|
309
|
+
:::warning
|
310
|
+
Currently `shouldRevalidate` works under csr and streaming ssr.
|
311
|
+
:::
|
312
|
+
|
309
313
|
In each routing component (`layout.tsx`, `page.tsx`, `$.tsx`), we can export a `shouldRevalidate` function, which is triggered each time a route changes in the project. This function controls which routes' data are reloaded, and when it returns true, the data for the corresponding route is reloaded. data of the corresponding route will be reloaded.
|
310
314
|
|
311
315
|
```ts title="routes/user/layout.tsx"
|
@@ -330,6 +334,37 @@ export const shouldRevalidate: ShouldRevalidateFunction = ({
|
|
330
334
|
For more details about the `shouldRevalidate` function, please refer to [react-router](https://reactrouter.com/en/main/route/should-revalidate)
|
331
335
|
:::
|
332
336
|
|
337
|
+
### Client Loader
|
338
|
+
|
339
|
+
:::info
|
340
|
+
1. This feature requires version x.36.0 or above, and it‘s recommended to use the latest version of the framework.
|
341
|
+
2. Only SSR projects have Client Loaders, while in CSR projects, it can be considered as the default Client Loader.
|
342
|
+
3. This feature can be used progressively and not every project needs it. For specific information, please refer to the explanation of applicable scenarios in the document below.
|
343
|
+
|
344
|
+
:::
|
345
|
+
|
346
|
+
#### Applicable scenarios
|
347
|
+
|
348
|
+
In the SSR project, the code in Data Loader will only be executed on the server side when the client performs SPA navigation.
|
349
|
+
The framework will send an HTTP request to the SSR service to trigger the execution of Data Loader.
|
350
|
+
However, in some scenarios, we may expect that requests sent by clients do not go through the SSR service and directly request data sources.
|
351
|
+
|
352
|
+
:::info
|
353
|
+
Why the Data Loader is only executed server-side in SSR projects can be found in [FAQ](#faq)
|
354
|
+
|
355
|
+
:::
|
356
|
+
|
357
|
+
For example, the following scenarios:
|
358
|
+
|
359
|
+
1. During SSR degradation, it is not desired for the framework to send requests to the SSR service to obtain data. Instead, direct requests to the data source are preferred.
|
360
|
+
2. There is some cache on the client side, and we don't want to request SSR service to fetch data.
|
361
|
+
|
362
|
+
In these scenarios, we can use Client Loader. After adding the Client Loader, in the following scenarios, the code in the Client Loader will be called instead of sending requests to SSR services:
|
363
|
+
|
364
|
+
1. After SSR is downgraded to CSR, when fetch data on the client side, Client Loader will be executed instead of the framework sending requests to Data Loader (Server) to fetch data.
|
365
|
+
2. When performing SPA navigation in SSR projects and fetch data, Client Loader will be executed.
|
366
|
+
|
367
|
+
|
333
368
|
### Incorrect usage
|
334
369
|
|
335
370
|
1. The `loader` can only return serializable data. In the SSR environment, the return value of the `loader` function will be serialized as a JSON string and then deserialized into an object on the client side. Therefore, the `loader` function cannot return non-serializable data (such as functions).
|
@@ -403,6 +438,16 @@ In CSR projects, `loader` is executed on the client side, and the BFF function c
|
|
403
438
|
|
404
439
|
In SSR projects, each `loader` is also a server-side interface. We recommend using the `loader` instead of the BFF function with an http method of `get` as the interface layer to avoid an extra layer of forwarding and execution.
|
405
440
|
|
441
|
+
2. Why is the Data Loader only executed on the server-side in SSR projects?
|
442
|
+
|
443
|
+
The Data Loader in our SSR project is designed to only run on the server side. The main reasons for sending requests from the client to the server during client-side rendering are as follows:
|
444
|
+
|
445
|
+
- **Simplified usage**, when using a server loader, the data fetching code for both the SSR and CSR phases is in the server loader (the real calls are made by the framework layer), and the code in the server loader doesn't need to care whether it's in a browser environment or a server-side environment.
|
446
|
+
- **Reducing data for network requests**, The server loader can be used as a BFF layer, which reduces the amount of data that needs to be fetched by the front-end at runtime.
|
447
|
+
- **Reduce client-side bundle size**, moving the logic code and its dependencies from the client to the server.
|
448
|
+
- **Improve maintainability**, moving the logic code to the server side reduces the direct impact of data logic on the front-end UI. In addition, the problem of mistakenly introducing server-side dependencies in the client-side bundle or client-side dependencies in the server-side bundle is also avoided.
|
449
|
+
|
450
|
+
|
406
451
|
## useLoader (old version)
|
407
452
|
|
408
453
|
**`useLoader`** is a legacy API in Modern.js v1. This API is a React Hook designed specifically for SSR applications, allowing developers to fetch data in components in isomorphic development.
|
@@ -46,6 +46,12 @@ import ModuleFederation from '@modern-js/builder-doc/docs/en/shared/module-feder
|
|
46
46
|
|
47
47
|
<ModuleFederation />
|
48
48
|
|
49
|
+
## Rsbuild
|
50
|
+
|
51
|
+
import Rsbuild from '@modern-js/builder-doc/docs/en/shared/rsbuild.md';
|
52
|
+
|
53
|
+
<Rsbuild />
|
54
|
+
|
49
55
|
## Rspack
|
50
56
|
|
51
57
|
import Rspack from '@modern-js/builder-doc/docs/en/shared/rspack.md';
|
File without changes
|
@@ -31,6 +31,7 @@ export default defineConfig({
|
|
31
31
|
- `disablePrerender`: `boolean = fasle`, 为了兼容旧数据请求方式 - `useLoader`, 默认情况下 Modern.js 会对组件进行一次预渲染即有两次渲染。
|
32
32
|
开发者在保证项目中没有使用 useLoader Api 情况下, 可通过配置 `disablePrerender=true`来减少一次渲染。
|
33
33
|
- `unsafeHeaders`: `string[] = []`, 为了安全考虑,Modern.js 不会往 SSR_DATA 添加过多的内容。开发者可以通过该配置,对需要注入的 headers 进行配置。
|
34
|
+
- `scriptLoading`: `'defer' | 'blocking' | 'module' | 'async'`, 配置同 [html.scriptLoading](/configure/app/html/script-loading),支持 ssr 注入的 script 设置为 async 加载方式。优先级为 `ssr.scriptLoading` > `html.scriptLoading`
|
34
35
|
|
35
36
|
```ts title="modern.config.ts"
|
36
37
|
export default defineConfig({
|
@@ -41,6 +42,7 @@ export default defineConfig({
|
|
41
42
|
inlineScript: false,
|
42
43
|
disablePrerender: true,
|
43
44
|
unsafeHeaders: ['User-Agent'],
|
45
|
+
scriptLoading: 'async',
|
44
46
|
},
|
45
47
|
},
|
46
48
|
});
|
@@ -25,27 +25,18 @@ import InitRspackApp from '@site-docs/components/init-rspack-app';
|
|
25
25
|
:::tip
|
26
26
|
在使用 Rspack 作为打包工具时,由于部分能力尚在开发中,以下 features 暂时无法使用,我们将在未来提供支持:
|
27
27
|
|
28
|
-
- Storybook 调试
|
29
28
|
- 客户端渲染(CSR)使用 [useLoader](/guides/basic-features/data/data-fetch.html)
|
30
29
|
|
31
30
|
:::
|
32
31
|
|
33
32
|
## 开启 Rspack 构建
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
```bash
|
38
|
-
$ pnpm run new
|
39
|
-
? 请选择你想要的操作 启用可选功能
|
40
|
-
? 请选择功能名称 启用「Rspack 构建」
|
41
|
-
```
|
42
|
-
|
43
|
-
执行以上命令后,在 `modern.config.ts` 中添加 Rspack 相关配置即可:
|
34
|
+
从 Modern.js MAJOR_VERSION.46.0 版本起,在一个已有的 Modern.js 项目中,你仅需在 `modern.config.ts` 中添加以下配置,即可启用 Rspack 构建:
|
44
35
|
|
45
36
|
```diff title=modern.config.ts
|
46
37
|
import { appTools, defineConfig } from '@modern-js/app-tools';
|
47
38
|
|
48
|
-
|
39
|
+
export default defineConfig({
|
49
40
|
plugins: [
|
50
41
|
appTools({
|
51
42
|
+ bundler: 'experimental-rspack',
|
@@ -54,13 +45,70 @@ import { appTools, defineConfig } from '@modern-js/app-tools';
|
|
54
45
|
});
|
55
46
|
```
|
56
47
|
|
48
|
+
:::tip
|
49
|
+
如果你当前版本低于 MAJOR_VERSION.46.0, 可通过执行 `npx modern upgrade` 进行升级。
|
50
|
+
:::
|
51
|
+
|
57
52
|
import RspackPrecautions from '@modern-js/builder-doc/docs/zh/shared/rspackPrecautions.md';
|
58
53
|
|
59
54
|
<RspackPrecautions />
|
60
55
|
|
61
56
|
## 配置迁移
|
62
57
|
|
63
|
-
|
58
|
+
Modern.js 中 [tools.webpack](/configure/app/tools/webpack) 和 [tools.webpackChain](/configure/app/tools/webpack-chain) 配置仅在 webpack 模式下生效,开启 Rspack 构建能力后,可根据实际使用场景决定是否修改为 [tools.rspack](/configure/app/tools/rspack) 或 [tools.bundlerChain](/configure/app/tools/bundler-chain)。
|
59
|
+
|
60
|
+
```diff
|
61
|
+
export default {
|
62
|
+
tools: {
|
63
|
+
- webppack: (config, { env }) => {
|
64
|
+
+ rspack: (config, { env }) => {
|
65
|
+
if (env === 'development') {
|
66
|
+
config.devtool = 'cheap-module-eval-source-map';
|
67
|
+
}
|
68
|
+
return config;
|
69
|
+
},
|
70
|
+
- webpackChain: (chain, { env }) => {
|
71
|
+
+ bundlerChain: (chain, { env }) => {
|
72
|
+
if (env === 'development') {
|
73
|
+
chain.devtool('cheap-module-eval-source-map');
|
74
|
+
}
|
75
|
+
},
|
76
|
+
},
|
77
|
+
};
|
78
|
+
```
|
79
|
+
|
80
|
+
|
81
|
+
:::tip
|
82
|
+
开启 Rspack 构建能力后,目前有小部分配置在 Rspack 中还不支持使用,如 [source.moduleScopes](/configure/app/source/module-scopes)、[security.sri](/configure/app/security/sri) 等。
|
83
|
+
|
84
|
+
对于不支持的配置,我们在文档中有标注 `打包工具: 仅支持 webpack` 或 `打包工具: 仅支持 rspack`,可参考具体配置介绍。
|
85
|
+
:::
|
86
|
+
|
87
|
+
## 修改转译配置
|
88
|
+
|
89
|
+
Modern.js 在 Rspack 模式下使用 Rspack [builtin:swc-loader](https://www.rspack.dev/zh/guide/builtin-swc-loader.html) 进行代码转译。
|
90
|
+
|
91
|
+
Modern.js 已对 `builtin:swc-loader` 的常见配置提供了更方便的配置方式,如:通过 [source.transformImport](/configure/app/source/transform-import) 配置组件库按需引入。如果对 `builtin:swc-loader` 有自定义配置的需求,可参考以下代码:
|
92
|
+
|
93
|
+
```ts
|
94
|
+
export default {
|
95
|
+
tools: {
|
96
|
+
bundlerChain: (chain, { CHAIN_ID }) => {
|
97
|
+
chain.module
|
98
|
+
.rule(CHAIN_ID.RULE.JS)
|
99
|
+
.use(CHAIN_ID.USE.SWC)
|
100
|
+
.tap(options => {
|
101
|
+
options.xxx = '';
|
102
|
+
return options;
|
103
|
+
});
|
104
|
+
},
|
105
|
+
}
|
106
|
+
};
|
107
|
+
```
|
108
|
+
|
109
|
+
:::tip
|
110
|
+
在启用 Rspack 构建时,babel-loader 默认不会被启用。如需添加 babel 插件,可通过 [tools.babel](/configure/app/tools/babel) 配置,此时会产生额外的编译开销,在一定程度上拖慢 Rspack 构建速度。
|
111
|
+
:::
|
64
112
|
|
65
113
|
## Rspack 和 Modern.js 的版本关系
|
66
114
|
|
@@ -68,9 +116,9 @@ import RspackPrecautions from '@modern-js/builder-doc/docs/zh/shared/rspackPreca
|
|
68
116
|
|
69
117
|
但 Modern.js 对于 Rspack 的依赖方式为锁版本方式(非自动升级),由于发版周期不同步等原因,可能会出现 Modern.js 内集成的 Rspack 版本落后于 Rspack 最新版本的情况。
|
70
118
|
|
71
|
-
当你执行 dev / build 命令时,Modern.js
|
119
|
+
当你执行 dev / build 命令时,Modern.js 会在开启调试模式时自动打印当前使用的 Rspack 版本:
|
72
120
|
|
73
|
-

|
74
122
|
|
75
123
|
#### 修改内置 Rspack 版本
|
76
124
|
|
@@ -84,7 +132,6 @@ import RspackPrecautions from '@modern-js/builder-doc/docs/zh/shared/rspackPreca
|
|
84
132
|
"overrides": {
|
85
133
|
"@rspack/core": "nightly",
|
86
134
|
"@rspack/plugin-react-refresh": "nightly",
|
87
|
-
"@rspack/plugin-html": "nightly"
|
88
135
|
}
|
89
136
|
}
|
90
137
|
}
|
@@ -232,9 +232,21 @@ function ErrorElement() {
|
|
232
232
|
}
|
233
233
|
```
|
234
234
|
|
235
|
+
## 为爬虫等待所有内容加载完毕
|
236
|
+
|
237
|
+
流式传输可以提高用户体验,因为当页面内容可用时,用户可以及时感知到它们。
|
238
|
+
|
239
|
+
然而,当一个爬虫访问该页面时,它可能需要先加载所有内容,直接输出整个 HTML,而不是渐进式地加载它。
|
240
|
+
|
241
|
+
Modern.js 使用 [isbot](https://www.npmjs.com/package/isbot) 对请求的 `uesr-agent`, 以判断请求是否来自爬虫。
|
242
|
+
|
235
243
|
:::info 补充信息
|
236
244
|
|
237
245
|
1. [Deferred Data](https://reactrouter.com/en/main/guides/deferred)
|
238
246
|
2. [New Suspense SSR Architecture in React 18](https://github.com/reactwg/react-18/discussions/37)
|
239
247
|
|
240
248
|
:::
|
249
|
+
|
250
|
+
import StreamSSRPerformance from '@site-docs/components/stream-ssr-performance';
|
251
|
+
|
252
|
+
<StreamSSRPerformance />
|
@@ -6,7 +6,7 @@ sidebar_position: 14
|
|
6
6
|
|
7
7
|
[CSS Modules](https://github.com/css-modules/css-modules) 让我们能以模块化的方式编写 CSS 代码,并且可以在 JavaScript 文件中导入和使用这些样式。使用 CSS Modules 可以自动生成唯一的类名,隔离不同模块之间的样式,避免类名冲突。
|
8
8
|
|
9
|
-
|
9
|
+
Modern.js 默认支持使用 CSS Modules,无需添加额外的配置。我们约定使用 `[name].module.css` 文件名来启用 CSS Modules。
|
10
10
|
|
11
11
|
以下样式文件会被视为 CSS Modules:
|
12
12
|
|
@@ -299,6 +299,10 @@ defer 的具体用法请查看 [defer](https://reactrouter.com/en/main/guides/de
|
|
299
299
|
|
300
300
|
### `shouldRevalidate`
|
301
301
|
|
302
|
+
:::warning
|
303
|
+
目前 `shouldRevalidate` 会在 csr 和 streaming ssr 下生效。
|
304
|
+
:::
|
305
|
+
|
302
306
|
在每个路由组件(`layout.tsx`,`page.tsx`, `$.tsx`)中,我们可以导出一个 `shouldRevalidate` 函数,在每次项目中的路由变化时,这个函数会触发,该函数可以控制要重新加载哪些路由中的数据,当这个函数返回 true, 对应路由的数据就会重新加载。
|
303
307
|
|
304
308
|
```ts title="routes/user/layout.tsx"
|
@@ -323,6 +327,66 @@ export const shouldRevalidate: ShouldRevalidateFunction = ({
|
|
323
327
|
`shouldRevalidate` 函数的更多信息可以参考 [react-router](https://reactrouter.com/en/main/route/should-revalidate)
|
324
328
|
:::
|
325
329
|
|
330
|
+
### Client Loader
|
331
|
+
|
332
|
+
:::info
|
333
|
+
1. 这个 feature 需要 x.36.0 以上版本,推荐使用框架最新版本
|
334
|
+
2. 只有 SSR 项目中有 Client Loader,CSR 项目中可以认为默认就是 Client Loader
|
335
|
+
3. 这个特性可以渐进使用,并不是每个项目都需要,具体可以看下面文档适用场景的说明
|
336
|
+
|
337
|
+
:::
|
338
|
+
|
339
|
+
#### 适用场景
|
340
|
+
|
341
|
+
在 SSR 项目中,Data Loader 中的代码只会在服务端执行,当客户端进行 SPA 导航时,
|
342
|
+
框架会发送一个 http 请求到 SSR 服务,触发 Data Loader 的执行,
|
343
|
+
但有些场景下,我们可能期望在客户端发送的请求不经过 SSR 服务,直接请求数据源。
|
344
|
+
|
345
|
+
:::info
|
346
|
+
为什么 SSR 项目中 Data Loader 只会在服务端执行可参考 [常见问题](#常见问题)
|
347
|
+
|
348
|
+
:::
|
349
|
+
|
350
|
+
例如以下场景:
|
351
|
+
|
352
|
+
1. 在 SSR 降级时,不希望框架向 SSR 服务发送请求获取数据,希望能直接请求后端服务。
|
353
|
+
2. 在客户端有一些缓存,不希望请求 SSR 服务获取数据。
|
354
|
+
|
355
|
+
这些场景下,我们可以使用 Client Loader, 添加 Client Loader 后,在以下的场景,会调用 Client Loader 中的代码,而不再像 SSR 服务发送请求:
|
356
|
+
|
357
|
+
1. SSR 降级为 CSR 后,在客户端获取数据时,会执行 Client Loader 代替框架发送请求到 Data Loader(Server) 获取数据。
|
358
|
+
2. SSR 项目进行 SPA 跳转时,获取数据,会执行 Clinet Loader。
|
359
|
+
|
360
|
+
|
361
|
+
#### 使用方式
|
362
|
+
|
363
|
+
:::warning
|
364
|
+
要使用 client loader,必须有对应的 server loader(data loader)
|
365
|
+
:::
|
366
|
+
|
367
|
+
1. 如果原有项目中 loader 是以 `.loader.ts` 文件为约定的,需要修改 `.loader.ts` 为 `.data.ts`(如果 loader 是在 `.data.ts` 文件中定义,忽略这个步骤)。
|
368
|
+
|
369
|
+
- 将 `.loader.ts` 文件重命名为 `.data.ts`
|
370
|
+
- 将文件中的代码做以下改动:
|
371
|
+
```ts
|
372
|
+
// xxx.loader.ts
|
373
|
+
export default () => {}
|
374
|
+
|
375
|
+
// xxx.data.ts
|
376
|
+
export const loader = () => {}
|
377
|
+
```
|
378
|
+
|
379
|
+
|
380
|
+
2. 添加 client loader,client loader API 中的入参和 data loader 是一致的。
|
381
|
+
|
382
|
+
```
|
383
|
+
// xxx.data.client.ts
|
384
|
+
export const loader = () => {}
|
385
|
+
```
|
386
|
+
|
387
|
+
|
388
|
+
|
389
|
+
|
326
390
|
### 错误用法
|
327
391
|
|
328
392
|
1. `loader` 中只能返回可序列化的数据,在 SSR 环境下,`loader` 函数的返回值会被序列化为 JSON 字符串,然后在客户端被反序列化为对象。因此,`loader` 函数中不能返回不可序列化的数据(如函数)。
|
@@ -394,6 +458,17 @@ export const loader = async (): Promise<ProfileData> => {
|
|
394
458
|
|
395
459
|
在 SSR 项目中,每个 `loader` 也是一个服务端接口,我们推荐使用 `loader` 替代 http method 为 `get` 的 BFF 函数,作为接口层,避免多一层转发和执行。
|
396
460
|
|
461
|
+
|
462
|
+
2. 为什么 SSR 项目中 Data Loader 只会在服务端执行?
|
463
|
+
|
464
|
+
我们设计 SSR 项目中 Data Loader 只会在服务端,在客户端渲染时,由框架发送请求到服务端主要有以下原因:
|
465
|
+
|
466
|
+
- **简化使用方式**,有 server loader 后,SSR 阶段和 CSR 阶段数据获取的操作都可以放在 server loader 中(真实的调用由框架层去做),server loader 中的代码无需关心是在浏览器环境中还是服务端环境中。
|
467
|
+
- **减少网络请求的数据**,作为 BFF 层,可以减少前端运行时需要获取的数据。
|
468
|
+
- **减少客户端 bundle 体积**,将逻辑代码及其依赖,从客户端移动到了服务端。
|
469
|
+
- **提高可维护性**,将逻辑代码移动到服务端,减少了数据逻辑对前端 UI 的直接影响。此外,也避免了客户端 bundle 中误引入服务端依赖,或服务端 bundle 中误引入客户端依赖的问题。
|
470
|
+
|
471
|
+
|
397
472
|
## useLoader(旧版)
|
398
473
|
|
399
474
|
**`useLoader`** 是 Modern.js 老版本中的 API。该 API 是一个 React Hook,专门提供给 SSR 应用使用,让开发者能同构的在组件中获取数据。
|
@@ -46,6 +46,12 @@ import ModuleFederation from '@modern-js/builder-doc/docs/zh/shared/module-feder
|
|
46
46
|
|
47
47
|
<ModuleFederation />
|
48
48
|
|
49
|
+
## Rsbuild
|
50
|
+
|
51
|
+
import Rsbuild from '@modern-js/builder-doc/docs/zh/shared/rsbuild.md';
|
52
|
+
|
53
|
+
<Rsbuild />
|
54
|
+
|
49
55
|
## Rspack
|
50
56
|
|
51
57
|
import Rspack from '@modern-js/builder-doc/docs/zh/shared/rspack.md';
|
package/package.json
CHANGED
@@ -15,17 +15,17 @@
|
|
15
15
|
"modern",
|
16
16
|
"modern.js"
|
17
17
|
],
|
18
|
-
"version": "2.
|
18
|
+
"version": "2.46.0",
|
19
19
|
"publishConfig": {
|
20
20
|
"registry": "https://registry.npmjs.org/",
|
21
21
|
"access": "public",
|
22
22
|
"provenance": true
|
23
23
|
},
|
24
24
|
"dependencies": {
|
25
|
-
"@modern-js/sandpack-react": "2.
|
25
|
+
"@modern-js/sandpack-react": "2.46.0"
|
26
26
|
},
|
27
27
|
"peerDependencies": {
|
28
|
-
"@modern-js/builder-doc": "^2.
|
28
|
+
"@modern-js/builder-doc": "^2.46.0"
|
29
29
|
},
|
30
30
|
"devDependencies": {
|
31
31
|
"classnames": "^2",
|
@@ -35,12 +35,12 @@
|
|
35
35
|
"ts-node": "^10.9.1",
|
36
36
|
"typescript": "^5",
|
37
37
|
"fs-extra": "^10",
|
38
|
-
"rspress": "1.
|
39
|
-
"@rspress/shared": "1.
|
38
|
+
"rspress": "1.9.3",
|
39
|
+
"@rspress/shared": "1.9.3",
|
40
40
|
"@types/node": "^16",
|
41
41
|
"@types/fs-extra": "9.0.13",
|
42
|
-
"@modern-js/doc-plugin-auto-sidebar": "2.
|
43
|
-
"@modern-js/builder-doc": "2.
|
42
|
+
"@modern-js/doc-plugin-auto-sidebar": "2.46.0",
|
43
|
+
"@modern-js/builder-doc": "2.46.0"
|
44
44
|
},
|
45
45
|
"scripts": {
|
46
46
|
"dev": "rspress dev",
|