@modern-js/main-doc 0.0.0-next-1681194540734 → 0.0.0-next-1681212960572

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/CHANGELOG.md CHANGED
@@ -1,12 +1,19 @@
1
1
  # @modern-js/main-doc
2
2
 
3
- ## 0.0.0-next-1681194540734
3
+ ## 0.0.0-next-1681212960572
4
4
 
5
5
  ### Patch Changes
6
6
 
7
+ - e91ec97bd0: feat(app-tools): export mergeConfig function
8
+
9
+ feat(app-tools): 导出 mergeConfig 函数
10
+
11
+ - 42700c13bd: chore: improve ssr docs, add more use case for node/web code split
12
+ chore: 优化 ssr 文档,为 node/web 代码分割添加更多使用场景
7
13
  - Updated dependencies [1feacdc7d6]
8
14
  - Updated dependencies [348306d413]
9
- - @modern-js/builder-doc@0.0.0-next-1681194540734
15
+ - Updated dependencies [42700c13bd]
16
+ - @modern-js/builder-doc@0.0.0-next-1681212960572
10
17
 
11
18
  ## 2.12.0
12
19
 
@@ -5,6 +5,10 @@ title: useLoader
5
5
 
6
6
  Isomorphic API, usually used to make asynchronous requests. When SSR, the server level uses `useLoader` to prefetch the data, and the browser side also reuses this part of the data.
7
7
 
8
+ :::tip
9
+ When using Rspack as the bundler, the useLoader API is not currently supported.
10
+ :::
11
+
8
12
  ## Usage
9
13
 
10
14
  ```ts
@@ -19,17 +19,33 @@ Server runtime configuration can be configured in the `modern.server-runtime.con
19
19
 
20
20
  ## Configure in the configuration file
21
21
 
22
- Modern.js configuration files are defined in the root path of the project, and supports `.js`, `.ts` and `.mjs` formats:
22
+ Modern.js configuration files are defined in the root path of the project, and supports `.ts`, `.js` and `.mjs` formats:
23
23
 
24
- - `modern.config.js`
25
24
  - `modern.config.ts`
25
+ - `modern.config.js`
26
26
  - `modern.config.mjs`
27
27
 
28
- ### modern.config.js
28
+ ### modern.config.ts (recommended)
29
29
 
30
- You can use JavaScript syntax in the `modern.config.js` file and it is more flexible than in the `package.json` file.
30
+ We recommend using configuration files in `.ts` format, which provides friendly TypeScript type hints to help you avoid configuration errors.
31
31
 
32
- For example, you can define configuration options for function types in `modern.config.js`:
32
+ Import the `defineConfig` tool function from `@modern-js/app-tools`, which will help you with configuration type derivation and type completion:
33
+
34
+ ```ts title="modern.config.ts"
35
+ import { defineConfig } from '@modern-js/app-tools';
36
+
37
+ export default defineConfig({
38
+ source: {
39
+ alias: {
40
+ '@common': './src/common',
41
+ },
42
+ },
43
+ });
44
+ ```
45
+
46
+ ### modern.config.js
47
+
48
+ If you are developing a non-TypeScript project, you can use the configuration file in .js format:
33
49
 
34
50
  ```js title="modern.config.js"
35
51
  export default {
@@ -51,24 +67,6 @@ export default {
51
67
  };
52
68
  ```
53
69
 
54
- ### modern.config.ts (recommended)
55
-
56
- We recommend using configuration files in `.ts` format, which provides friendly TypeScript type hints to help you avoid configuration errors.
57
-
58
- Import the `defineConfig` tool function from `@modern-js/app-tools`, which will help you with configuration type derivation and type completion:
59
-
60
- ```ts title="modern.config.ts"
61
- import { defineConfig } from '@modern-js/app-tools';
62
-
63
- export default defineConfig({
64
- source: {
65
- alias: {
66
- '@common': './src/common',
67
- },
68
- },
69
- });
70
- ```
71
-
72
70
  ### Export Configuration Function
73
71
 
74
72
  Modern.js supports exporting a function in the configuration file, and you can dynamically compute the configuration in the function and return it to Modern.js.
@@ -200,3 +198,47 @@ modern.config.local.ts
200
198
  modern.config.local.js
201
199
  modern.config.local.mjs
202
200
  ```
201
+
202
+ ## Merge Multiple Configurations
203
+
204
+ In some cases, you may need to merge multiple configurations into one configuration. You can use the `mergeConfig` util to merge multiple configurations.
205
+
206
+ The `mergeConfig` function accepts an array as a parameter, and each item in the array is a configuration object. `mergeConfig` will deeply merge each configuration object in the array, automatically merge multiple functions into an array, and returns a merged configuration object.
207
+
208
+ ### Example
209
+
210
+ ```ts title="modern.config.ts"
211
+ import { mergeConfig } from '@modern-js/app-tools';
212
+
213
+ const config1 = {
214
+ dev: {
215
+ port: 3000,
216
+ },
217
+ tools: {
218
+ postcss: () => console. log('config1');
219
+ },
220
+ };
221
+ const config2 = {
222
+ dev: {
223
+ port: 3001,
224
+ },
225
+ tools: {
226
+ postcss: () => console. log('config2');
227
+ },
228
+ };
229
+
230
+ const mergedConfig = mergeConfig([config1, config2]);
231
+ ```
232
+
233
+ In the above example, the merged configuration object is:
234
+
235
+ ```ts
236
+ const mergedConfig = {
237
+ dev: {
238
+ port: 3001,
239
+ },
240
+ tools: {
241
+ postcss: [() => console.log('config1'), () => console.log('config2')],
242
+ },
243
+ };
244
+ ```
@@ -246,6 +246,21 @@ if (process.env.MODERN_TARGET === 'browser') {
246
246
  }
247
247
  ```
248
248
 
249
+ After packaging in the development environment, SSR and CSR artifacts will be compiled into the following content. Therefore, there will be no more errors due to Web API in the SSR environment:
250
+
251
+ ```ts
252
+ // SSR production
253
+ if (false) {
254
+ }
255
+
256
+ // CSR production
257
+ if (true) {
258
+ document.addEventListener('load', () => {
259
+ console.log('document load');
260
+ });
261
+ }
262
+ ```
263
+
249
264
  :::note
250
265
  For more information, see [environment variables](/guides/basic-features/env-vars).
251
266
 
@@ -253,7 +268,9 @@ For more information, see [environment variables](/guides/basic-features/env-var
253
268
 
254
269
  ### Use File Suffix
255
270
 
256
- In the second case, the Treeshaking method does not guarantee that the code is completely separated. Modern.js also supports the packaging file of SSR Bundle and CSR Bundle products through the file suffixed with `.node.`.
271
+ However, in the second case, for example, when `fs-extra` is imported into the code, it internally uses the Node API with side effects. If it is directly referenced in the component, it will cause CSR loading errors.
272
+
273
+ Env vars is not effective in this situation. Modern.js also supports distinguishing SSR Bundle and CSR Bundle packaging files through files with the `.node.` suffix.
257
274
 
258
275
  For example, the import of `fs-extra` in the code, when it is directly referenced to the component, will cause the CSR to load an error. You can create `.ts` and `.node.ts` files of the same name as a layer of proxy:
259
276
 
@@ -280,7 +297,27 @@ export const loader = () => {
280
297
 
281
298
  ### Independent File
282
299
 
283
- Both of the above methods will bring some burden to the developer. Modern.js based on [Nested Routing](/guides/basic-features/routes) developed and designed [Data Fetch](/guides/basic-features/data-fetch) to separate CSR and SSR code.
300
+ Both of the above methods can bring some mental burden to developers. In real business scenarios, we found that most of the mixed Node/Web code occurs in data requests.
301
+
302
+ Therefore, Modern.js developed a [Data Fetch](/guides/basic-features/data-fetch) to separate CSR and SSR code based on [Nested Routing](/guides/basic-features/routes).
303
+
304
+ We can separate **data request** and **component code** by using independent files. Write component logic in `routes/page.tsx` and data request logic in `routes/page.loader.ts`.
305
+
306
+ ```ts title="routes/page.tsx"
307
+ export default Page = () => {
308
+ return <div>Hello World<div>
309
+ }
310
+ ```
311
+
312
+ ```ts title="routes/page.loader.tsx"
313
+ import fse from 'fs-extra';
314
+ export default () => {
315
+ const file = fse.readFileSync('./myfile');
316
+ return {
317
+ ...
318
+ };
319
+ }
320
+ ```
284
321
 
285
322
  ## Remote Request
286
323
 
@@ -317,7 +354,7 @@ The streaming SSR of Modern.js is implemented based on React Router, and the mai
317
354
 
318
355
  ### Return async data
319
356
 
320
- ```ts title='page.loader.ts'
357
+ ```ts title="page.loader.ts"
321
358
  import { defer, type LoaderFunctionArgs } from '@modern-js/runtime/router';
322
359
 
323
360
  interface User {
@@ -351,7 +388,7 @@ therefore, the parameter passed to `defer` is `{data: user}`.
351
388
 
352
389
  `defer` can also receive asynchronous data and synchronous data at the same time. For example:
353
390
 
354
- ```ts title='page.loader.ts'
391
+ ```ts title="page.loader.ts"
355
392
 
356
393
  // skip some codes
357
394
 
@@ -388,7 +425,7 @@ export default ({ params }: LoaderFunctionArgs) => {
388
425
 
389
426
  Use the `Await` component to render the data returned asynchronously from the Data Loader. For example:
390
427
 
391
- ```tsx title='page.tsx'
428
+ ```tsx title="page.tsx"
392
429
  import { Await, useLoaderData } from '@modern-js/runtime/router';
393
430
  import { Suspense } from 'react';
394
431
  import type { Data } from './page.loader';
@@ -430,7 +467,7 @@ So, here we import like this: `import type { Data } from './page.loader'`;
430
467
 
431
468
  You can also get the asynchronous data returned by Data Loader through `useAsyncValue`. For example:
432
469
 
433
- ```tsx title='page.tsx'
470
+ ```tsx title="page.tsx"
434
471
  import { useAsyncValue } from '@modern-js/runtime/router';
435
472
 
436
473
  // skip some codes
@@ -468,7 +505,7 @@ export default Page;
468
505
  The `errorElement` property of the `Await` component can be used to handle errors thrown when the Data Loader executes or when a child component renders.
469
506
  For example, we intentionally throw an error in the Data Loader function:
470
507
 
471
- ```ts title='page.loader.ts'
508
+ ```ts title="page.loader.ts"
472
509
  import { defer } from '@modern-js/runtime/router';
473
510
 
474
511
  export default () => {
@@ -484,7 +521,7 @@ export default () => {
484
521
 
485
522
  Then use `useAsyncError` to get the error, and assign the component used to render the error to the `errorElement` property of the `Await` component:
486
523
 
487
- ```tsx title='page.ts'
524
+ ```tsx title="page.ts"
488
525
  import { Await, useAsyncError, useLoaderData } from '@modern-js/runtime/router';
489
526
  import { Suspense } from 'react';
490
527
 
@@ -345,6 +345,28 @@ export const config = (): AppConfig => {
345
345
  };
346
346
  ```
347
347
 
348
+ ### Prefetch
349
+
350
+ When using convention-based routing, Modern.js will automatically split chunks according to the route, and when the user accesses a specific route, the corresponding resources will be loaded automatically, which can effectively reduce the first screen loading time. However, this also brings a problem, when the user accesses a route, if the asset corresponding to that route is not yet loaded, a white screen will appear.
351
+
352
+ In this case you can show a custom `loading` component by defining a `loading` component before the static resource is loaded.
353
+
354
+ To further improve the user experience and reduce time of loading, Modern.js supports defining the `prefetch` property on the Link component to load static resources and data in advance, with three optional values for the `prefetch` property:
355
+
356
+ ```
357
+ <Link prefetch="intent" to="page">
358
+ ```
359
+
360
+ :::info
361
+ - This feature is currently only supported in Webpack projects, not in Rspack projects.
362
+ - Prefetching of data will only prefetch the data returned from the data loader of the SSR project.
363
+
364
+ :::
365
+
366
+ - `none`, the default value, will not do prefetch, no additional behavior.
367
+ - `intent`, the value we recommend for most scenarios, will automatically start loading the corresponding resources and the data defined in the data loader when you mouse over the Link, and will automatically unload it when the mouse is moved away. In our tests, even a direct click can reduce the loading time by about 200ms.
368
+ - `render`, when the Link component renders, it will load the corresponding resources and the data defined in the data loader.
369
+
348
370
  ## Self-controlled routing
349
371
 
350
372
  With `src/App.tsx` as the agreed entry, Modern.js will not do additional operations with multiple routes, developers can use the React Router 6 API for development by themselves, for example:
@@ -5,6 +5,10 @@ title: useLoader
5
5
 
6
6
  一个同构的 API,通常会用来做异步请求。当 SSR 的时候,服务端使用 `useLoader` 预加载数据,同时浏览器端也会复用这部分数据。
7
7
 
8
+ :::tip
9
+ 在使用 Rspack 作为打包工具时,暂不支持使用 useLoader API。
10
+ :::
11
+
8
12
  ## 使用姿势
9
13
 
10
14
  ```ts
@@ -19,17 +19,33 @@ Modern.js 不支持同时在 package.json 中和 modern.config.ts 中配置同
19
19
 
20
20
  ## 在配置文件中配置
21
21
 
22
- Modern.js 的配置文件定义在项目的根目录下,支持 `.js`, `.ts` 和 `.mjs` 格式:
22
+ Modern.js 的配置文件定义在项目的根目录下,支持 `.ts`, `.js` 和 `.mjs` 格式:
23
23
 
24
- - `modern.config.js`
25
24
  - `modern.config.ts`
25
+ - `modern.config.js`
26
26
  - `modern.config.mjs`
27
27
 
28
- ### modern.config.js
28
+ ### modern.config.ts(推荐)
29
+
30
+ 我们推荐使用 .ts 格式的配置文件,它提供了友好的 TypeScript 类型提示,从而帮助你避免配置中的错误。
31
+
32
+ 从 `@modern-js/app-tools` 中导入 `defineConfig` 工具函数, 它会帮助你进行配置的类型推导和类型补全:
33
+
34
+ ```ts title="modern.config.ts"
35
+ import { defineConfig } from '@modern-js/app-tools';
36
+
37
+ export default defineConfig({
38
+ source: {
39
+ alias: {
40
+ '@common': './src/common',
41
+ },
42
+ },
43
+ });
44
+ ```
29
45
 
30
- `modern.config.js` 中可以使用 JavaScript 语法,因此比 `package.json` 更加灵活。
46
+ ### modern.config.js
31
47
 
32
- 比如,你可以在 `modern.config.js` 中定义函数类型的配置选项:
48
+ 如果你在开发一个非 TypeScript 项目,可以使用 .js 格式的配置文件:
33
49
 
34
50
  ```js title="modern.config.js"
35
51
  export default {
@@ -51,24 +67,6 @@ export default {
51
67
  };
52
68
  ```
53
69
 
54
- ### modern.config.ts(推荐)
55
-
56
- 我们推荐使用 .ts 格式的配置文件,它提供了友好的 TypeScript 类型提示,从而帮助你避免配置中的错误。
57
-
58
- 从 `@modern-js/app-tools` 中导入 `defineConfig` 工具函数, 它会帮助你进行配置的类型推导和类型补全:
59
-
60
- ```ts title="modern.config.ts"
61
- import { defineConfig } from '@modern-js/app-tools';
62
-
63
- export default defineConfig({
64
- source: {
65
- alias: {
66
- '@common': './src/common',
67
- },
68
- },
69
- });
70
- ```
71
-
72
70
  ### 导出配置函数
73
71
 
74
72
  Modern.js 支持在配置文件中导出一个函数,你可以在函数中动态计算配置,并返回给 Modern.js。
@@ -134,7 +132,7 @@ $ modern build -c modern.prod.config.js
134
132
 
135
133
  ## 在 package.json 中配置(不推荐)
136
134
 
137
- 除了配置文件外,也可以在 `package.json` 中的 `modernConfig` 字段下设置配置选项,如:
135
+ 除了配置文件外,你也可以在 `package.json` 中的 `modernConfig` 字段下设置配置项,如:
138
136
 
139
137
  ```json title="package.json"
140
138
  {
@@ -200,3 +198,47 @@ modern.config.local.ts
200
198
  modern.config.local.js
201
199
  modern.config.local.mjs
202
200
  ```
201
+
202
+ ## 合并多份配置
203
+
204
+ 在某些情况下,你可能需要将多份配置合并为一份配置,此时你可以使用 `mergeConfig` 工具函数来合并多个配置。
205
+
206
+ `mergeConfig` 函数接受一个数组作为参数,数组中的每一项都是一个配置对象,`mergeConfig` 会将数组中的每一项配置对象进行深层合并,自动将多个函数项合并为数组,最终返回一个合并后的配置对象。
207
+
208
+ ### 示例
209
+
210
+ ```ts title="modern.config.ts"
211
+ import { mergeConfig } from '@modern-js/app-tools';
212
+
213
+ const config1 = {
214
+ dev: {
215
+ port: 3000,
216
+ },
217
+ tools: {
218
+ postcss: () => console.log('config1');
219
+ },
220
+ };
221
+ const config2 = {
222
+ dev: {
223
+ port: 3001,
224
+ },
225
+ tools: {
226
+ postcss: () => console.log('config2');
227
+ },
228
+ };
229
+
230
+ const mergedConfig = mergeConfig([config1, config2]);
231
+ ```
232
+
233
+ 在以上示例中,合并后的配置对象为:
234
+
235
+ ```ts
236
+ const mergedConfig = {
237
+ dev: {
238
+ port: 3001,
239
+ },
240
+ tools: {
241
+ postcss: [() => console.log('config1'), () => console.log('config2')],
242
+ },
243
+ };
244
+ ```
@@ -215,16 +215,23 @@ const App = () => {
215
215
  export default App;
216
216
  ```
217
217
 
218
- 在组件文件中引入 Node API,通常情况下是因为使用了 Data Loader,例如:
218
+ 在组件文件中引入 Node API,通常情况下是因为使用了 `useLoader`,例如:
219
219
 
220
220
  ```ts
221
221
  import fse from 'fs-extra';
222
- export const loader = () => {
223
- const file = fse.readFileSync('./myfile');
224
- return {
225
- ...
226
- };
222
+ import { useLoader } from '@modern-js/runtime'
223
+
224
+ const App = () => {
225
+ const { data } = useLoader(async () => {
226
+ const file = fse.readFileSync('./myfile');
227
+ return {
228
+ ...
229
+ };
230
+ })
231
+
232
+ return <div>Hello World</div>;
227
233
  };
234
+ export default App;
228
235
  ```
229
236
 
230
237
  ### 环境变量区分
@@ -239,16 +246,32 @@ if (process.env.MODERN_TARGET === 'browser') {
239
246
  }
240
247
  ```
241
248
 
249
+ 开发环境打包后,SSR 产物和 CSR 产物会被编译成以下内容。因此 SSR 环境中不会再因为 Web API 报错:
250
+
251
+ ```ts
252
+ // SSR 产物
253
+ if (false) {
254
+ }
255
+
256
+ // CSR 产物
257
+ if (true) {
258
+ document.addEventListener('load', () => {
259
+ console.log('document load');
260
+ });
261
+ }
262
+ ```
263
+
242
264
  :::note
243
265
  更多内容可以查看[环境变量](/guides/basic-features/env-vars)。
244
-
245
266
  :::
246
267
 
247
268
  ### 文件后缀区分
248
269
 
249
- 但例如第二种情况,Treeshaking 的方式并不能保证代码被完全分离。Modern.js 也支持通过 `.node.` 后缀的文件来区分 SSR Bundle 和 CSR Bundle 产物的打包文件。
270
+ 但例如第二种情况,在代码中引入了 `fs-extra`,它内部有使用了 Node API 的副作用,如果直接引用到组件中,会造成 CSR 加载报错。
271
+
272
+ 环境变量的方式并不能在这种情况下生效,Modern.js 也支持通过 `.node.` 后缀的文件来区分 SSR Bundle 和 CSR Bundle 产物的打包文件。
250
273
 
251
- 例如在代码中引入了 `fs-extra`,这时候直接引用到组件中,会造成 CSR 加载报错。可以创建同名的 `.ts` 和 `.node.ts` 文件做一层代理:
274
+ 可以创建同名的 `.ts` 和 `.node.ts` 文件做一层代理:
252
275
 
253
276
  ```ts title="compat.ts"
254
277
  export const readFileSync: any = () => {};
@@ -273,7 +296,27 @@ export const loader = () => {
273
296
 
274
297
  ### 独立文件
275
298
 
276
- 上述两种方式,都会为开发者带来一些心智负担。Modern.js 基于[嵌套路由](/guides/basic-features/routes)开发设计了[更简单的方案](/guides/basic-features/data-fetch)来分离 CSR 和 SSR 的代码。
299
+ 上述两种方式,都会为开发者带来一些心智负担。在真实的业务中,我们发现大多数的 Node / Web 代码混用都出现在数据请求中。
300
+
301
+ 因此,Modern.js 基于[嵌套路由](/guides/basic-features/routes)开发设计了[更简单的方案](/guides/basic-features/data-fetch)来分离 CSR 和 SSR 的代码。
302
+
303
+ 我们可以通过独立文件来分离**数据请求**与**组件代码**。在 `routes/page.tsx` 中编写组件逻辑,在 `routes/page.loader.ts` 中编写数据请求逻辑。
304
+
305
+ ```ts title="routes/page.tsx"
306
+ export default Page = () => {
307
+ return <div>Hello World<div>
308
+ }
309
+ ```
310
+
311
+ ```ts title="routes/page.loader.tsx"
312
+ import fse from 'fs-extra';
313
+ export default () => {
314
+ const file = fse.readFileSync('./myfile');
315
+ return {
316
+ ...
317
+ };
318
+ }
319
+ ```
277
320
 
278
321
  ## 接口请求
279
322
 
@@ -307,7 +350,7 @@ Modern.js 的流式渲染基于 React Router 实现,主要涉及 API 有:
307
350
 
308
351
  ### 异步获取数据
309
352
 
310
- ```ts title='page.loader.ts'
353
+ ```ts title="page.loader.ts"
311
354
  import { defer, type LoaderFunctionArgs } from '@modern-js/runtime/router';
312
355
 
313
356
  interface User {
@@ -336,11 +379,11 @@ export default ({ params }: LoaderFunctionArgs) => {
336
379
  ```
337
380
 
338
381
  `user` 是一个 Promise 类型的对象,表示需要异步获取的数据,通过 `defer` 处理需要异步获取的 `user`。注意,`defer` 必须接收一个对象类型的参数,
339
- 因此, 传入 `defer` 的参数为 `{data: user}`。
382
+ 因此, 传入 `defer` 的参数为:`{ data: user }`
340
383
 
341
384
  `defer` 还可以同时接收异步数据和同步数据。例如:
342
385
 
343
- ```ts title='page.loader.ts'
386
+ ```ts title="page.loader.ts"
344
387
  // 省略部分代码
345
388
 
346
389
  export default ({ params }: LoaderFunctionArgs) => {
@@ -374,7 +417,7 @@ export default ({ params }: LoaderFunctionArgs) => {
374
417
 
375
418
  通过 `Await` 组件,可以获取到 Data Loader 中异步返回的数据,然后进行渲染。例如:
376
419
 
377
- ```tsx title='page.tsx'
420
+ ```tsx title="page.tsx"
378
421
  import { Await, useLoaderData } from '@modern-js/runtime/router';
379
422
  import { Suspense } from 'react';
380
423
  import type { Data } from './page.loader';
@@ -454,7 +497,7 @@ export default Page;
454
497
  `Await` 组件的 `errorElement` 属性,可以用来处理当 Data Loader 执行时,或者子组件渲染时抛出的错误。
455
498
  例如,我们故意在 Data Loader 函数中抛出错误:
456
499
 
457
- ```ts title='page.loader.ts'
500
+ ```ts title="page.loader.ts"
458
501
  import { defer } from '@modern-js/runtime/router';
459
502
 
460
503
  export default () => {
@@ -470,7 +513,7 @@ export default () => {
470
513
 
471
514
  然后通过 `useAsyncError` 获取错误,并将用于渲染错误信息的组件赋值给 `Await` 组件的 `errorElement` 属性:
472
515
 
473
- ```tsx title='page.ts'
516
+ ```tsx title="page.ts"
474
517
  import { Await, useAsyncError, useLoaderData } from '@modern-js/runtime/router';
475
518
  import { Suspense } from 'react';
476
519
 
@@ -424,6 +424,29 @@ export const init = (context: RuntimeContext) => {
424
424
  };
425
425
  ```
426
426
 
427
+ ### Prefetch
428
+
429
+ 在约定式路由下, Modern.js 会根据路由,自动地对路由进行分片,当用户访问具体的路由时,会自动加载对应的分片,这样可以有效地减少首屏加载的时间。但这也带来了一个问题,当用户访问一个路由时,如果该路由对应的分片还未加载完成,就会出现白屏的情况。
430
+ 这种情况下你可以通过定义 `loading` 组件,在静态资源加载完成前,展示一个自定义的 `loading` 组件。
431
+
432
+ 为了进一步提升用户体验,减少 loading 的时间,Modern.js 支持在 Link 组件上定义 `prefetch` 属性,可以提前对静态资源和数据进行加载, `prefetch` 属性有三个可选值:
433
+
434
+ ```
435
+ <Link prefetch="intent" to="page">
436
+ ```
437
+
438
+ :::info
439
+ - 该功能目前仅在 Webpack 项目中支持,Rspack 项目暂不支持。
440
+ - 对数据的预加载目前只会预加载 SSR 项目中 [data loader](/guides/basic-features/data-fetch) 中返回的数据。
441
+
442
+ :::
443
+
444
+ - `none`, 默认值,不会做 prefetch,没有任何额外的行为。
445
+ - `intent`,这是我们推荐大多数场景下使用的值,当你把鼠标放在 Link 上时,会自动开始加载对应的分片和 data loader 中定义的数据,当鼠标移开时,会自动取消加载。在我们的测试中,即使是直接点击,也能减少大约 200ms 的加载时间。
446
+ - `render`,当 Link 组件渲染时,就会加载对应的分片和 data loader 中定义的数据。
447
+
448
+
449
+
427
450
  ## 自控式路由
428
451
 
429
452
  以 `src/App.tsx` 为约定的入口,Modern.js 不会多路由做额外的操作,开发者可以自行使用 React Router 6 的 API 进行开发,例如:
@@ -469,3 +492,20 @@ export default defineConfig({
469
492
  },
470
493
  });
471
494
  ```
495
+
496
+ ### 常见问题
497
+
498
+ 1. 产物中的代码是 es2015+ 的,期望产物中是 es5 的代码
499
+
500
+ react-router^6 的目前默认产物是 es2020 的,如果需要产物中是 es5 的代码,可以配置 `source.include`,让 react-router 相关包经过 bundler 编译 :
501
+
502
+ ```
503
+ source: {
504
+ source: {
505
+ include: [/@remix-run\/router/, /react-router-dom/, /react-router/],
506
+ }
507
+ }
508
+ ```
509
+
510
+
511
+
package/package.json CHANGED
@@ -11,13 +11,13 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "0.0.0-next-1681194540734",
14
+ "version": "0.0.0-next-1681212960572",
15
15
  "publishConfig": {
16
16
  "registry": "https://registry.npmjs.org/",
17
17
  "access": "public"
18
18
  },
19
19
  "peerDependencies": {
20
- "@modern-js/builder-doc": "0.0.0-next-1681194540734"
20
+ "@modern-js/builder-doc": "0.0.0-next-1681212960572"
21
21
  },
22
22
  "devDependencies": {
23
23
  "classnames": "^2",
@@ -29,9 +29,9 @@
29
29
  "fs-extra": "^10",
30
30
  "@types/node": "^16",
31
31
  "@types/fs-extra": "^9",
32
- "@modern-js/builder-doc": "0.0.0-next-1681194540734",
33
- "@modern-js/doc-tools": "0.0.0-next-1681194540734",
34
- "@modern-js/doc-plugin-auto-sidebar": "0.0.0-next-1681194540734"
32
+ "@modern-js/builder-doc": "0.0.0-next-1681212960572",
33
+ "@modern-js/doc-tools": "0.0.0-next-1681212960572",
34
+ "@modern-js/doc-plugin-auto-sidebar": "0.0.0-next-1681212960572"
35
35
  },
36
36
  "scripts": {
37
37
  "dev": "modern dev",