@modern-js/main-doc 2.44.0 → 2.45.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  });
@@ -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.
@@ -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
  });
@@ -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 应用使用,让开发者能同构的在组件中获取数据。
package/package.json CHANGED
@@ -15,17 +15,17 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.44.0",
18
+ "version": "2.45.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.44.0"
25
+ "@modern-js/sandpack-react": "2.45.0"
26
26
  },
27
27
  "peerDependencies": {
28
- "@modern-js/builder-doc": "^2.44.0"
28
+ "@modern-js/builder-doc": "^2.45.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "classnames": "^2",
@@ -39,8 +39,8 @@
39
39
  "@rspress/shared": "1.8.4",
40
40
  "@types/node": "^16",
41
41
  "@types/fs-extra": "9.0.13",
42
- "@modern-js/doc-plugin-auto-sidebar": "2.44.0",
43
- "@modern-js/builder-doc": "2.44.0"
42
+ "@modern-js/doc-plugin-auto-sidebar": "2.45.0",
43
+ "@modern-js/builder-doc": "2.45.0"
44
44
  },
45
45
  "scripts": {
46
46
  "dev": "rspress dev",