@modern-js/main-doc 2.6.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +17 -0
  3. package/README.md +2 -2
  4. package/en/apis/app/commands.mdx +2 -0
  5. package/en/apis/app/hooks/config/upload.mdx +10 -0
  6. package/en/apis/app/runtime/model/connect.mdx +1 -1
  7. package/en/apis/app/runtime/model/model_.mdx +1 -1
  8. package/en/apis/app/runtime/model/use-model.mdx +1 -1
  9. package/en/apis/app/runtime/web-server/hook.mdx +2 -2
  10. package/en/apis/app/runtime/web-server/middleware.mdx +33 -9
  11. package/en/components/enable-bff.mdx +4 -4
  12. package/en/components/init-rspack-app.mdx +7 -0
  13. package/en/configure/app/bff/enable-handle-web.mdx +24 -0
  14. package/en/configure/app/server/enable-framework-ext.mdx +1 -1
  15. package/en/configure/app/server/ssr.mdx +18 -0
  16. package/en/guides/advanced-features/bff/_category_.json +1 -1
  17. package/en/guides/advanced-features/eslint.mdx +30 -32
  18. package/en/guides/advanced-features/low-level.mdx +1 -1
  19. package/en/guides/advanced-features/rspack-start.mdx +13 -17
  20. package/en/guides/advanced-features/ssr.mdx +210 -5
  21. package/en/guides/advanced-features/web-server.mdx +87 -20
  22. package/en/guides/{css/tailwindcss.mdx → basic-features/css.mdx} +60 -3
  23. package/en/guides/basic-features/env-vars.mdx +4 -0
  24. package/en/guides/concept/builder.mdx +1 -1
  25. package/en/guides/topic-detail/framework-plugin/extend.mdx +20 -19
  26. package/en/guides/topic-detail/framework-plugin/hook-list.mdx +156 -155
  27. package/en/guides/topic-detail/framework-plugin/hook.mdx +58 -43
  28. package/en/guides/topic-detail/framework-plugin/implement.mdx +47 -49
  29. package/en/guides/topic-detail/framework-plugin/introduction.mdx +22 -23
  30. package/en/guides/topic-detail/framework-plugin/plugin-api.mdx +13 -13
  31. package/en/guides/topic-detail/framework-plugin/relationship.mdx +30 -30
  32. package/en/guides/topic-detail/generator/plugin/develop.mdx +1 -1
  33. package/en/guides/topic-detail/micro-frontend/c01-introduction.mdx +17 -17
  34. package/en/guides/topic-detail/micro-frontend/c02-development.mdx +76 -78
  35. package/en/guides/topic-detail/micro-frontend/c03-main-app.mdx +57 -51
  36. package/en/guides/topic-detail/micro-frontend/c04-communicate.mdx +11 -11
  37. package/en/guides/topic-detail/micro-frontend/c05-mixed-stack.mdx +13 -13
  38. package/en/guides/topic-detail/model/auto-actions.mdx +18 -21
  39. package/en/guides/topic-detail/model/computed-state.mdx +27 -25
  40. package/en/guides/topic-detail/model/define-model.mdx +14 -14
  41. package/en/guides/topic-detail/model/faq.mdx +12 -13
  42. package/en/guides/topic-detail/model/manage-effects.mdx +43 -52
  43. package/en/guides/topic-detail/model/model-communicate.mdx +47 -45
  44. package/en/guides/topic-detail/model/performance.mdx +22 -23
  45. package/en/guides/topic-detail/model/quick-start.mdx +29 -28
  46. package/en/guides/topic-detail/model/redux-integration.mdx +7 -7
  47. package/en/guides/topic-detail/model/test-model.mdx +11 -11
  48. package/en/guides/topic-detail/model/typescript-best-practice.mdx +16 -15
  49. package/en/guides/topic-detail/model/use-model.mdx +40 -45
  50. package/en/guides/topic-detail/model/use-out-of-modernjs.mdx +16 -16
  51. package/en/guides/troubleshooting/cli.mdx +2 -2
  52. package/en/tutorials/first-app/c03-css.mdx +1 -1
  53. package/package.json +5 -5
  54. package/zh/apis/app/commands.mdx +2 -0
  55. package/zh/apis/app/hooks/config/upload.mdx +12 -2
  56. package/zh/apis/app/runtime/model/connect.mdx +1 -1
  57. package/zh/apis/app/runtime/model/model_.mdx +1 -1
  58. package/zh/apis/app/runtime/model/use-model.mdx +1 -1
  59. package/zh/apis/app/runtime/web-server/hook.mdx +2 -4
  60. package/zh/apis/app/runtime/web-server/middleware.mdx +30 -10
  61. package/zh/apis/monorepo/commands/gen-release-note.mdx +3 -3
  62. package/zh/components/enable-bff.mdx +4 -4
  63. package/zh/components/init-rspack-app.mdx +7 -0
  64. package/zh/components/release-note.mdx +1 -1
  65. package/zh/configure/app/bff/enable-handle-web.mdx +24 -0
  66. package/zh/configure/app/server/enable-framework-ext.mdx +1 -1
  67. package/zh/configure/app/server/ssr.mdx +19 -1
  68. package/zh/guides/advanced-features/bff/_category_.json +1 -1
  69. package/zh/guides/advanced-features/rspack-start.mdx +13 -17
  70. package/zh/guides/advanced-features/ssr.mdx +210 -4
  71. package/zh/guides/advanced-features/web-server.mdx +81 -16
  72. package/zh/guides/{css/tailwindcss.mdx → basic-features/css.mdx} +60 -3
  73. package/zh/guides/basic-features/env-vars.mdx +4 -0
  74. package/zh/guides/concept/builder.mdx +1 -1
  75. package/zh/guides/topic-detail/changesets/github.mdx +2 -2
  76. package/zh/guides/topic-detail/changesets/release-note.mdx +1 -1
  77. package/zh/guides/topic-detail/framework-plugin/plugin-api.mdx +2 -2
  78. package/zh/guides/topic-detail/generator/plugin/develop.mdx +1 -1
  79. package/zh/guides/topic-detail/model/faq.mdx +1 -1
  80. package/zh/guides/topic-detail/model/manage-effects.mdx +1 -1
  81. package/zh/guides/topic-detail/model/model-communicate.mdx +1 -1
  82. package/zh/guides/topic-detail/model/performance.mdx +1 -1
  83. package/zh/guides/topic-detail/model/quick-start.mdx +2 -2
  84. package/zh/guides/topic-detail/model/use-model.mdx +3 -3
  85. package/zh/tutorials/first-app/c03-css.mdx +1 -1
  86. package/en/guides/css/_category_.json +0 -5
  87. package/en/guides/css/css-in-js.mdx +0 -40
  88. package/en/guides/css/css-modules.mdx +0 -87
  89. package/en/guides/css/less-sass.mdx +0 -17
  90. package/en/guides/css/postcss.mdx +0 -79
  91. package/zh/guides/css/_category_.json +0 -5
  92. package/zh/guides/css/css-in-js.mdx +0 -40
  93. package/zh/guides/css/css-modules.mdx +0 -87
  94. package/zh/guides/css/less-sass.mdx +0 -17
  95. package/zh/guides/css/postcss.mdx +0 -80
@@ -44,8 +44,9 @@ And it provides elegant degradation processing. Once the SSR request fails, it w
44
44
  However, developers still need to pay attention to the fallback of data, such as `null` values or data returns that do not as expect. Avoid React rendering errors or messy rendering results when SSR.
45
45
 
46
46
  :::info
47
- When using Data Loader, data fetching happens before rendering, Modern.js still supports fetching data when the component is rendered. See [Data Fetch](/guides/basic-features/data-fetch).
47
+ 1. When you request the page on client-side page transitions, Modern.js sends an API request to the server, which runs Data Loader function.
48
48
 
49
+ 2. When using Data Loader, data fetching happens before rendering, Modern.js still supports fetching data when the component is rendered. See [Data Fetch](/guides/basic-features/data-fetch).
49
50
  :::
50
51
 
51
52
  ## Keep Rendering Consistent
@@ -288,9 +289,9 @@ In addition, some backend interfaces, or general gateways, will verify according
288
289
 
289
290
  Be sure to filter the `host` field if you really need to pass through all request headers.
290
291
 
291
- ## Stream SSR
292
+ ## Streaming SSR
292
293
 
293
- Modern.js supports streaming rendering in React 18, the default rendering mode can be modified with the following configuration:
294
+ Modern.js supports streaming rendering in React 18. Opt in it with the following configuration:
294
295
 
295
296
  ```json
296
297
  {
@@ -302,7 +303,211 @@ Modern.js supports streaming rendering in React 18, the default rendering mode c
302
303
  }
303
304
  ```
304
305
 
305
- :::note
306
- At present Modern.js built-in data fetch does not support streaming rendering. If app need it, developers can build it according to the demo of React Stream SSR.
306
+ The streaming SSR of Modern.js is implemented based on React Router, and the main APIs involved are:
307
+
308
+ - [`defer`](https://reactrouter.com/en/main/utils/defer): This utility allows you to defer values returned from loaders by passing promises instead of resolved values.
309
+ - [`Await`](https://reactrouter.com/en/main/components/await): Used to render deferred values with automatic error handling.
310
+ - [`useAsyncValue`](https://reactrouter.com/en/main/hooks/use-async-value):Returns the resolved data from the nearest `<Await>` ancestor component.
311
+
312
+
313
+ ### Return async data
314
+
315
+ ```ts title='page.loader.ts'
316
+ import { defer, type LoaderFunctionArgs } from '@modern-js/runtime/router';
317
+
318
+ interface User {
319
+ name: string;
320
+ age: number;
321
+ }
322
+
323
+ export interface Data {
324
+ data: User;
325
+ }
326
+
327
+ export default ({ params }: LoaderFunctionArgs) => {
328
+ const userId = params.id;
329
+
330
+ const user = new Promise<User>(resolve => {
331
+ setTimeout(() => {
332
+ resolve({
333
+ name: `user-${userId}`,
334
+ age: 18,
335
+ });
336
+ }, 200);
337
+ });
338
+
339
+ return defer({ data: user });
340
+ };
341
+
342
+ ```
343
+
344
+ `user` is of `Promise` type, which means the data will be obtained asynchronously. Note that `defer` must accept an object type parameter,
345
+ therefore, the parameter passed to `defer` is `{data: user}`.
346
+
347
+ `defer` can also receive asynchronous data and synchronous data at the same time. For example:
348
+
349
+ ```ts title='page.loader.ts'
350
+
351
+ // skip some codes
352
+
353
+ export default ({ params }: LoaderFunctionArgs) => {
354
+ const userId = params.id;
355
+
356
+ const user = new Promise<User>(resolve => {
357
+ setTimeout(() => {
358
+ resolve({
359
+ name: `user-${userId}`,
360
+ age: 18,
361
+ });
362
+ }, 200);
363
+ });
364
+
365
+ const otherData = new Promise<string>(resolve => {
366
+ setTimeout(() => {
367
+ resolve('some sync data');
368
+ }, 200);
369
+ });
370
+
371
+ return defer({
372
+ data: user,
373
+ other: await otherData
374
+ });
375
+ };
376
+
377
+ ```
378
+
379
+ `await` is added before `otherData`, so the data is obtained synchronously. It can be passed to `defer` with the data `user` at the same time.
380
+
381
+
382
+ ### Render async data
383
+
384
+ Use the `Await` component to render the data returned asynchronously from the Data Loader. For example:
385
+
386
+ ```ts title='page.tsx'
387
+ import { Await, useLoaderData } from '@modern-js/runtime/router';
388
+ import { Suspense } from 'react';
389
+ import type { Data } from './page.loader';
390
+
391
+ const Page = () => {
392
+ const data = useLoaderData() as Data;
393
+
394
+ return (
395
+ <div>
396
+ User info:
397
+ <Suspense fallback={<div id="loading">loading user data ...</div>}>
398
+ <Await resolve={data.data}>
399
+ {(user) => {
400
+ return (
401
+ <div id="data">
402
+ name: {user.name}, age: {user.age}
403
+ </div>
404
+ );
405
+ }}
406
+ </Await>
407
+ </Suspense>
408
+ </div>
409
+ );
410
+ };
411
+
412
+ export default Page;
413
+ ```
414
+
415
+ `Await` needs to be wrapped inside the `Suspense` component. The `resolve` of `Await` passes in the data acquired asynchronously by the Data Loader. When the data acquisition is completed,
416
+ the obtained data is rendered through the [Render Props](https://reactjs.org/docs/render-props.html) mode. When the data acquisition is in pending status, the
417
+ content set by the `fallback` property of the `Suspense` component will display.
418
+
419
+
420
+ :::warning Warning
421
+ When importing a type from a Data Loader file, you need to use the `import type` syntax to ensure that only type information is imported, which can prevent the Data Loader code from being packaged into the client bundle.
422
+
423
+ So, here we import like this: `import type { Data } from './page.loader'`;
424
+ :::
425
+
426
+ You can also get the asynchronous data returned by Data Loader through `useAsyncValue`. For example:
427
+
428
+ ```
429
+ ```ts title='page.tsx'
430
+ import { useAsyncValue } from '@modern-js/runtime/router';
431
+
432
+ // skip some codes
433
+
434
+ const UserInfo = () => {
435
+ const user = useAsyncValue();
436
+
437
+ return (
438
+ <div>
439
+ name: {user.name}, age: {user.age}
440
+ </div>
441
+ )
442
+ }
443
+
444
+ const Page = () => {
445
+ const data = useLoaderData() as Data;
446
+
447
+ return (
448
+ <div>
449
+ User info:
450
+ <Suspense fallback={<div id="loading">loading user data ...</div>}>
451
+ <Await resolve={data.data}>
452
+ <UserInfo />
453
+ </Await>
454
+ </Suspense>
455
+ </div>
456
+ );
457
+ };
458
+
459
+ export default Page;
460
+ ```
461
+
462
+ ### Error handling
463
+
464
+ 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.
465
+ For example, we intentionally throw an error in the Data Loader function:
466
+
467
+ ```ts title='page.loader.ts'
468
+ import { defer } from '@modern-js/runtime/router';
469
+
470
+ export default () => {
471
+ const data = new Promise((resolve, reject) => {
472
+ setTimeout(() => {
473
+ reject(new Error('error occurs'));
474
+ }, 200);
475
+ });
476
+
477
+ return defer({ data });
478
+ };
479
+ ```
480
+
481
+ Then use `useAsyncError` to get the error, and assign the component used to render the error to the `errorElement` property of the `Await` component:
482
+
483
+ ```ts title='page.ts'
484
+ import { Await, useAsyncError, useLoaderData } from '@modern-js/runtime/router';
485
+ import { Suspense } from 'react';
486
+
487
+ export default function Page() {
488
+ const data = useLoaderData();
489
+
490
+ return (
491
+ <div>
492
+ Error page
493
+ <Suspense fallback={<div>loading ...</div>}>
494
+ <Await resolve={data.data} errorElement={<ErrorElement />}>
495
+ {(data: any) => {
496
+ return <div>never displayed</div>;
497
+ }}
498
+ </Await>
499
+ </Suspense>
500
+ </div>
501
+ );
502
+ }
503
+
504
+ function ErrorElement() {
505
+ const error = useAsyncError() as Error;
506
+ return <p>Something went wrong! {error.message}</p>;
507
+ }
508
+ ```
307
509
 
510
+ :::info More
511
+ 1. [Deferred Data](https://reactrouter.com/en/main/guides/deferred)
512
+ 2. [New Suspense SSR Architecture in React 18](https://github.com/reactwg/react-18/discussions/37)
308
513
  :::
@@ -1,23 +1,37 @@
1
1
  ---
2
2
  title: Custom Web Server
3
- sidebar_position: 2
3
+ sidebar_position: 3
4
4
  ---
5
5
  # Custom Web Server
6
6
 
7
- Modern.js 作为以客户端为中心的开发框架,对服务端的定制能力较弱。而在有些开发场景下,需要定制特殊的服务端逻辑,例如用户鉴权、请求预处理、添加页面渲染骨架等。
7
+ As a client side-centric development framework, Modern.js has weak customization capabilities on the server side. In some development scenarios, special server level logic needs to be customized, such as user authentication, request preprocessing, and adding page rendering skeletons.
8
8
 
9
- 因此 Modern.js 提供了一种功能,让项目可以在给定的范围内扩展 Modern.js 内置的 Web Server,来实现相应的需求。
9
+ Some developers may be wondering, Modern.js already provides [BFF](/guides/advanced-features/bff/function.html), why do you need **Custom Web Server**.
10
10
 
11
- ## 创建自定义 Web Server
11
+ Because by default, page routing does not go through BFF, it has no way to provide server-side custom logic for page access. The reason for this design is that we do not want the service that controls the page to be bound to the BFF service, so as to avoid the BFF framework restricting how the page is deployed.
12
12
 
13
- 在项目根目录执行 `pnpm run new` 命令,按照如下选择,开启「自定义 Web Serve」功能:
13
+ For example, hosting pages separately from BFF, deploying page services to non-Node environments, or customizing for deployment platforms, etc.
14
+
15
+ For the above reasons, Modern.js provides three ways that projects can customize server level capabilities progressively according to their needs.
16
+
17
+ :::warning
18
+ The three extension methods cannot work at the same time, and developers need to choose the appropriate method according to the scenario.
19
+ :::
20
+
21
+ ## Extending Web Server with API
22
+
23
+ The first way is to customize the server level at a specific life cycle through the server level runtime API provided by Modern.js. The purpose of providing this way is that in some cases, developers do not need to control the full Web Server, but only need to add server level logic.
24
+
25
+ Because the full web server cannot be controlled this way, and the extension logic **only takes effect when the page is requested**. Therefore, it is relatively simple to apply to server level logic, and you do not want to create additional BFFs or BFFs and pages without common server level logic scenarios.
26
+
27
+ You can execute the'pnpm run new 'command in the project root directory to enable the "Custom Web Serve" function:
14
28
 
15
29
  ```bash
16
- ? 请选择你想要的操作 创建工程元素
17
- ? 创建工程元素 新建「自定义 Web Server」源码目录
30
+ ? Action Create project element
31
+ ? New "Custom Web Server" source code directory
18
32
  ```
19
33
 
20
- 执行命令后,在 `modern.config.ts` 中注册 Server 插件:
34
+ After executing the command, register the `@modern-js/plugin-server` plugin in `modern.config.ts`:
21
35
 
22
36
  ```ts title="modern.config.ts"
23
37
  import serverPlugin from '@modern-js/plugin-server';
@@ -27,31 +41,84 @@ export default defineConfig({
27
41
  });
28
42
  ```
29
43
 
30
- 项目目录下会新建 `server/index.ts` 文件,自定义逻辑在这个文件中编写。
44
+ After the function is turned on, the `server/index.ts` file will be automatically created in the project directory, and custom logic can be written in this file. Modern.js provides two types of APIs, **Hook** and **Middleware**, to extend Web Server.
45
+
46
+ ### Hook
31
47
 
32
- ## 使用 API 扩展 Web Server
48
+ The Hook provided by Modern.js is used to control the built-in logic in the Web Server, and all page requests go through the Hook.
33
49
 
34
- Modern.js 提供了 **Hook** **Middleware** 两类 API 来扩展 Web Server。
50
+ There are currently two Hooks provided, namely `AfterMatch` and `AfterRender`, which can be used to modify the rendering results. It can be written in `server/index.ts` like this:
35
51
 
36
- ### Hook
52
+ ```ts
53
+ import type { AfterMatchHook, AfterRenderHook } from '@modern-js/runtime/server';
54
+
55
+ export const afterMatch: AfterMatchHook = (ctx, next) => {
56
+ next();
57
+ }
58
+
59
+ export const afterRender: AfterRenderHook = (ctx, next) => {
60
+ next();
61
+ }
62
+ ```
37
63
 
38
- Hook 可以控制 Web Server 对请求处理的内置逻辑,非 BFF 请求会经过 Hook 的处理。
64
+ Projects should have the following best practices when using Hook:
39
65
 
40
- Hook 不可以使用运行时框架拓展。
66
+ 1. Permission verification in afterMatch.
67
+ 2. Do Rewrite and Redirect in afterMatch.
68
+ 3. Do HTML content injection in afterRender.
41
69
 
42
- 详细 API 可以查看 [Hook](/apis/app/runtime/web-server/hook)。
70
+ :::note
71
+ For more detail, see [Hook](/apis/app/runtime/web-server/hook)。
72
+ :::
43
73
 
44
74
  ### Middleware
45
75
 
46
- Middleware 可以为 Web Server 添加前置中间件,只有 SSR 请求会经过 Middleware 的处理。
76
+ For some projects, there may be more requirements at the server level, Modern.js provides Middleware to add pre-middleware for Web Server. It can only run in a Node environment, so if the project is deployed to another environment, such as a Worker environment, Middleware cannot be used.
47
77
 
48
- Middleware 可以使用运行时框架拓展。
78
+ Modern.js provides a set of APIs by default for projects to use:
49
79
 
50
- 详细 API 可以查看 [Hook](/apis/app/runtime/web-server/middleware)。
80
+ ```ts
81
+ import { Middlewre } from '@modern-js/runtime/server';
51
82
 
52
- ## 完全自定义的 Web Server
83
+ export const middleware = (context, next) => {
84
+ const { source: { req, res } } = context;
85
+ console.log(req.url);
86
+ next();
87
+ };
88
+ ```
53
89
 
54
90
  :::note
55
- 敬请期待
91
+ For more detail, see [Middleware] (/apis/app/runtime/web-server/middleware).
92
+ :::
93
+
94
+ Projects should have the following best practices when using Middleware:
95
+
96
+ 1. In Middleware, you can directly operate origin request and response objects, do event tracking, and inject Node services (databases, Redis, etc.) that may be used for SSR rendering.
97
+ 2. Marking and crawler optimization can be done in Middleware.
98
+ 3. In Middleware, you can ignore the default rendering and customize the rendering process.
99
+
100
+ **In general, in CSR projects, using Hook can basically meet all the needs of simple scenarios. In SSR projects, Middleware can be used for more complex Node extensions.**
101
+
102
+ ## Managed Page Requests with BFF
103
+
104
+ The second way is to use BFF to Managed page rendering. In this way, all requests will first hit the BFF service.
105
+
106
+ This method can uniformly control the server level logic of all requests through BFF. Therefore, it is suitable for scenarios where the server level logic is complex, and BFF and pages need common server level logic. But it still relies on the Web Server of Modern.js as a whole, and cannot run the logic on existing services.
107
+
108
+ To use this method, we need to first enable the "BFF" function through `pnpm new`. Then add [`bff.enableHandleWeb`](/configure/app/bff/enable-handle-web.html) configuration in the configuration file:
56
109
 
110
+ ```ts
111
+ export default defineConfig({
112
+ bff: {
113
+ enableHandleWeb: true,
114
+ },
115
+ });
116
+ ```
117
+
118
+ When this value is set to `true`, page request traffic also goes through the BFF, and the logic built into Modern.js for page rendering defaults to running as the last middleware for the BFF service.
119
+
120
+ ## Fully Customized Web Server
121
+
122
+ :::note
123
+ Comming soon..
57
124
  :::
@@ -2,7 +2,64 @@
2
2
  sidebar_position: 2
3
3
  ---
4
4
 
5
- # Tailwind CSS
5
+ # CSS Solutions
6
+
7
+ Modern.js has built-in multiple CSS solutions, including Less / Sass / Stylus preprocessor, PostCSS, CSS Modules, CSS-in-JS and Tailwind CSS.
8
+
9
+ ## Using Less, Sass and Stylus
10
+
11
+ Modern.js has built-in community popular CSS preprocessors such as Less, Sass.
12
+
13
+ By default, you don't need to configure anything for Less and Sass. If you need to customize loader config, you can configure [tools.less](/configure/app/tools/less), [tools.sass](/configure/app/tools/sass) to set it up.
14
+
15
+ You can also use Stylus in Modern.js, just install the Stylus plugin provided by Modern.js Builder, please refer to [Stylus Plugin](https://modernjs.dev/builder/en/plugins/plugin-stylus.html) for usage.
16
+
17
+ ## Using PostCSS
18
+
19
+ Modern.js has built-in [PostCSS](https://postcss.org/) to transform the CSS code.
20
+
21
+ Please refer to [Modern.js Builder - Using PostCSS](https://modernjs.dev/builder/en/guide/basic/css-usage.html#using-postcss) for detailed usage.
22
+
23
+ ## Using CSS Modules
24
+
25
+ Please read the [Using CSS Modules](https://modernjs.dev/builder/en/guide/basic/css-modules.html) chapter for a complete usage of CSS Modules.
26
+
27
+ ## Using CSS-in-JS
28
+
29
+ CSS-in-JS is a technology that can write CSS styles in JS files.
30
+
31
+ Modern.js integrates the CSS-in-JS library [styled-components](https://styled-components.com/) commonly used in the community, which uses the new feature of JavaScript [Tagged template](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates) to write CSS styles for components. You can use the [styled-components](https://styled-components.com/) API directly from `@modern-js/runtime/styled`.
32
+
33
+ When you need to write a `div` component with an internal font in red, you can do the following implementation:
34
+
35
+ ```js
36
+ import styled from '@modern-js/runtime/styled';
37
+
38
+ const RedDiv = styled.div`
39
+ color: red;
40
+ `;
41
+ ```
42
+
43
+ When you need to dynamically set the component style according to the `props` of the component, for example, when the attribute `primary` of `props` is `true`, the color of the button is white, and otherwise it is red. The implementation code is as follows:
44
+
45
+ ```js
46
+ import styled from '@modern-js/runtime/styled';
47
+
48
+ const Button = styled.button`
49
+ color: ${props => (props.primary ? 'white' : 'red')};
50
+ font-size: 1em;
51
+ `;
52
+ ```
53
+
54
+ For more usage of styled-components, please refer to [[styled-components official website](https://styled-components.com/) ].
55
+
56
+ Modern.js uses the Babel plugin [babel-plugin-styled-components](https://github.com/styled-components/babel-plugin-styled-components) internally, and the plugin can be configured through [tools.styledComponents](/configure/app/tools/styled-components).
57
+
58
+ :::tip
59
+ If you need to use [styled-jsx](https://www.npmjs.com/package/styled-jsx), [Emotion](https://emotion.sh/) and other CSS-in-JS libraries, you need to install the dependency of the corresponding library first. For specific usage, please refer to the official website of the corresponding library.
60
+ :::
61
+
62
+ ## Using Tailwind CSS
6
63
 
7
64
  [Tailwind CSS](https://tailwindcss.com/) is a CSS framework and design system based on Utility Class, which can quickly add common styles to components, and support flexible extension of theme styles. To use [Tailwind CSS](https://tailwindcss.com/) in the Modern.js, just execute `pnpm run new` in the project root directory and turn it on.
8
65
 
@@ -36,7 +93,7 @@ According to different needs, you can optionally import the CSS files provided b
36
93
 
37
94
  :::
38
95
 
39
- ## Tailwind CSS version
96
+ ### Tailwind CSS version
40
97
 
41
98
  Modern.js supports both Tailwind CSS v2 and v3. The framework will recognize the version of `tailwindcss` in the project `package.json` and apply the corresponding configuration. By default, we install Tailwind CSS v3 for you.
42
99
 
@@ -54,7 +111,7 @@ Both Tailwind CSS v2 and v3 do not support IE 11 browsers. For background, pleas
54
111
 
55
112
  If you use Tailwind CSS on IE 11 browser, some styles may not be available, please pay attention.
56
113
 
57
- ## Theme config
114
+ ### Theme config
58
115
 
59
116
  When you need to customize the [theme](https://tailwindcss.com/docs/theme) configuration of Tailwind CSS, you can modify it in the configuration [`source.designSystem`](/configure/app/source/design-system), for example, add a color theme `primary`:
60
117
 
@@ -8,6 +8,10 @@ Modern.js provides support for environment variables, including built-in environ
8
8
 
9
9
  ## Built-in Environment
10
10
 
11
+ ### ASSET_PREFIX
12
+
13
+ The current path prefix of resource file, which is a **read-only** environment variable.
14
+
11
15
  ### NODE_ENV
12
16
 
13
17
  The current execution environment and is a **read-only** environment variable whose have different values under different execution commands:
@@ -6,7 +6,7 @@ sidebar_position: 2
6
6
 
7
7
  **Modern.js uses [Modern.js Builder](https://modernjs.dev/builder) to build your Web App.**
8
8
 
9
- Modern.js Builder is one of the core components of Modern.js. It is A Build Engine for web development. and can be used independently of Modern.js. Modern.js Builder supports multiple bundlers such as webpack and rspack, and it uses webpack by default.
9
+ Modern.js Builder is one of the core components of Modern.js. It is A build engine for web development. and can be used independently of Modern.js. Modern.js Builder supports multiple bundlers such as webpack and Rspack, and it uses webpack by default.
10
10
 
11
11
  ## Build Architecture
12
12
 
@@ -1,24 +1,24 @@
1
1
  ---
2
- title: 扩展插件 Hook
2
+ title: Extending
3
3
  sidebar_position: 5
4
4
  ---
5
- # 扩展插件 Hook
5
+ # Extending Plugin Hooks
6
6
 
7
- 本小节介绍如何通过动态注册 [Hook 模型](/guides/topic-detail/framework-plugin/hook) 的方式来扩展插件 Hook。
7
+ This section describes how to extend plugin Hooks by dynamically registering [Hook models](/guides/topic-detail/framework-plugin/hook).
8
8
 
9
- ## 示例
9
+ ## Example
10
10
 
11
- 这里我们用一个简单的例子演示一下。假设我们要添加一些管理控制台输出信息的 Hook。
11
+ Here is a simple example to demonstrate how to extend plugin Hooks by adding Hooks that manage console output.
12
12
 
13
- 首先我们初始化一个空的项目文件,并添加基础依赖:
13
+ First, we initialize an empty project file and add basic dependencies:
14
14
 
15
15
  ```bash
16
16
  $ npx @modern-js/create modern-js-demo
17
17
  ```
18
18
 
19
- ### 创建 Hook
19
+ ### Creating Hooks
20
20
 
21
- 我们先创建一个 Hook 模型:
21
+ First, let's create a Hook model:
22
22
 
23
23
  ```ts title=config/plugin/myPlugin.ts
24
24
  import { createWaterfall } from '@modern-js/plugin';
@@ -26,7 +26,7 @@ import { createWaterfall } from '@modern-js/plugin';
26
26
  const message = createWaterfall<string[]>();
27
27
  ```
28
28
 
29
- 然后注册它:
29
+ then register:
30
30
 
31
31
  ```ts title=config/plugin/myPlugin.ts
32
32
  import type { CliPlugin } from '@modern-js/core';
@@ -40,7 +40,7 @@ export default (): CliPlugin => ({
40
40
  });
41
41
  ```
42
42
 
43
- 添加 Hook 类型:
43
+ add Hook types:
44
44
 
45
45
  ```ts title=config/plugin/myPlugin.ts
46
46
  declare module '@modern-js/core' {
@@ -50,9 +50,9 @@ declare module '@modern-js/core' {
50
50
  }
51
51
  ```
52
52
 
53
- ### 使用 Hook
53
+ ### Using Hooks
54
54
 
55
- 创建插件,通过 `commands` Hook 函数,添加命令处理逻辑:
55
+ Create a plugin and add command handling logic through the `commands` Hook function:
56
56
 
57
57
  ```ts title=config/plugin/myPlugin.ts
58
58
  import type { CliPlugin } from '@modern-js/core';
@@ -74,7 +74,7 @@ export default (): CliPlugin => ({
74
74
  });
75
75
  ```
76
76
 
77
- 最后 `config/plugin/myPlugin.ts` 的状态是:
77
+ now `config/plugin/myPlugin.ts` is:
78
78
 
79
79
  ```ts title=config/plugin/myPlugin.ts
80
80
  import { createWaterfall } from '@modern-js/plugin';
@@ -109,7 +109,7 @@ declare module '@modern-js/core' {
109
109
  }
110
110
  ```
111
111
 
112
- 然后在 `modern.config.ts` 中添加这个插件:
112
+ Then add this plugin in `modern.config.ts`:
113
113
 
114
114
  ```ts title="modern.config.ts"
115
115
  import { defineConfig } from '@modern-js/app-tools';
@@ -120,9 +120,9 @@ export default defineConfig({
120
120
  });
121
121
  ```
122
122
 
123
- 这时运行 `npx modern message` 就会执行相关逻辑,但由于没有收集到任何信息,所以控制台输出为空。
123
+ Now, run `npx modern message`, and the related logic will be executed, but no information is collected, so the console output is empty.
124
124
 
125
- 那这里我们添加一个:
125
+ add:
126
126
 
127
127
  ```ts title=config/plugin/otherPlugin.ts
128
128
  import type { CliPlugin } from '@modern-js/core';
@@ -140,7 +140,7 @@ export default (): CliPlugin => ({
140
140
  });
141
141
  ```
142
142
 
143
- 将它添加到配置中:
143
+ add to config:
144
144
 
145
145
  ```ts title="modern.config.ts"
146
146
  import { defineConfig } from '@modern-js/app-tools';
@@ -152,7 +152,7 @@ export default defineConfig({
152
152
  });
153
153
  ```
154
154
 
155
- 这时运行 `npx modern message` 就可以在控制台看到信息了:
155
+ run `npx modern message`, then we can get follow in console:
156
156
 
157
157
  ```bash
158
158
  $ modern message
@@ -160,4 +160,5 @@ $ modern message
160
160
  [foo] line 1
161
161
  ```
162
162
 
163
- 以上面这种方式就可以扩展出拥有各种能力的插件 Hook。
163
+ By using the above approach, you can extend plugin Hooks with various capabilities.
164
+