@modern-js/main-doc 2.58.3 → 2.60.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. package/docs/en/_meta.json +10 -5
  2. package/docs/en/apis/app/hooks/api/lambda.mdx +4 -48
  3. package/docs/en/apis/app/hooks/api/middleware.mdx +11 -0
  4. package/docs/en/apis/app/runtime/core/use-loader.mdx +1 -1
  5. package/docs/en/community/blog/v2-release-note.mdx +1 -1
  6. package/docs/en/components/enable-bff.mdx +19 -2
  7. package/docs/en/components/extend-bff-function.mdx +5 -0
  8. package/docs/en/components/init-app.mdx +0 -1
  9. package/docs/en/components/init-rspack-app.mdx +0 -1
  10. package/docs/en/components/other-plugins.mdx +0 -0
  11. package/docs/en/components/ssr-monitor.mdx +3 -0
  12. package/docs/en/configure/app/auto-load-plugin.mdx +4 -0
  13. package/docs/en/configure/app/output/ssg.mdx +52 -141
  14. package/docs/en/configure/app/plugins.mdx +2 -2
  15. package/docs/en/configure/app/tools/esbuild.mdx +1 -1
  16. package/docs/en/configure/app/tools/swc.mdx +1 -1
  17. package/docs/en/configure/app/tools/tailwindcss.mdx +1 -1
  18. package/docs/en/guides/_meta.json +0 -5
  19. package/docs/en/guides/advanced-features/_meta.json +3 -8
  20. package/docs/en/guides/advanced-features/bff/_meta.json +1 -1
  21. package/docs/en/guides/advanced-features/bff/extend-server.mdx +154 -0
  22. package/docs/en/guides/advanced-features/bff/frameworks.mdx +52 -123
  23. package/docs/en/guides/advanced-features/bff/function.mdx +108 -80
  24. package/docs/en/guides/advanced-features/bff/sdk.mdx +40 -51
  25. package/docs/en/guides/advanced-features/build-performance.mdx +6 -21
  26. package/docs/en/guides/advanced-features/page-performance/_meta.json +1 -0
  27. package/docs/en/guides/advanced-features/rspack-start.mdx +6 -14
  28. package/docs/en/guides/basic-features/_meta.json +31 -9
  29. package/docs/en/guides/basic-features/css/_meta.json +1 -0
  30. package/docs/en/guides/basic-features/css/css-in-js.mdx +34 -0
  31. package/docs/en/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -4
  32. package/docs/en/guides/basic-features/css/css.mdx +25 -0
  33. package/docs/en/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +5 -66
  34. package/docs/en/guides/basic-features/data/data-fetch.mdx +134 -235
  35. package/docs/en/guides/basic-features/data/data-write.mdx +66 -77
  36. package/docs/en/guides/basic-features/debug/_meta.json +1 -0
  37. package/docs/en/guides/basic-features/debug/rsdoctor.mdx +57 -0
  38. package/docs/en/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +2 -0
  39. package/docs/en/guides/basic-features/render/_meta.json +1 -0
  40. package/docs/en/guides/basic-features/render/ssg.mdx +208 -0
  41. package/docs/en/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +38 -50
  42. package/docs/en/guides/basic-features/render/ssr.mdx +301 -0
  43. package/docs/en/guides/basic-features/render/streaming-ssr.mdx +230 -0
  44. package/docs/en/guides/basic-features/routes.mdx +274 -263
  45. package/docs/en/guides/basic-features/static-assets/_meta.json +1 -0
  46. package/docs/en/guides/basic-features/static-assets.mdx +2 -2
  47. package/docs/en/guides/basic-features/testing/_meta.json +1 -0
  48. package/docs/en/guides/basic-features/testing/cypress.mdx +95 -0
  49. package/docs/en/guides/basic-features/testing/jest.mdx +148 -0
  50. package/docs/en/guides/basic-features/testing/playwright.mdx +111 -0
  51. package/docs/en/guides/basic-features/testing/vitest.mdx +100 -0
  52. package/docs/en/guides/concept/entries.mdx +9 -2
  53. package/docs/en/guides/deprecated.md +2 -0
  54. package/docs/en/guides/get-started/quick-start.mdx +1 -1
  55. package/docs/en/guides/get-started/tech-stack.mdx +4 -4
  56. package/docs/en/guides/topic-detail/_meta.json +0 -6
  57. package/docs/en/guides/topic-detail/generator/create/config.mdx +0 -10
  58. package/docs/en/guides/topic-detail/generator/create/use.mdx +0 -1
  59. package/docs/en/plugin/_meta.json +19 -0
  60. package/docs/en/plugin/cli-plugins/_meta.json +1 -0
  61. package/docs/en/plugin/cli-plugins/plugin-bff.mdx +5 -0
  62. package/docs/en/plugin/cli-plugins/plugin-ssg.mdx +5 -0
  63. package/docs/en/{guides/rsbuild-plugins → plugin/cli-plugins}/plugin-swc.mdx +7 -0
  64. package/docs/en/plugin/cli-plugins/plugin-tailwind.mdx +5 -0
  65. package/docs/en/plugin/cli-plugins.mdx +6 -0
  66. package/docs/en/{guides/advanced-features/rsbuild-plugin.mdx → plugin/introduction.mdx} +36 -11
  67. package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/extend.mdx +1 -1
  68. package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/implement.mdx +3 -3
  69. package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/plugin-api.mdx +2 -2
  70. package/docs/en/plugin/rsbuild-plugins/_meta.json +1 -0
  71. package/docs/en/plugin/rsbuild-plugins.mdx +3 -0
  72. package/docs/en/tutorials/first-app/c03-css.mdx +1 -1
  73. package/docs/zh/_meta.json +10 -5
  74. package/docs/zh/apis/app/hooks/api/lambda.mdx +5 -48
  75. package/docs/zh/apis/app/hooks/api/middleware.mdx +11 -0
  76. package/docs/zh/apis/app/runtime/core/use-loader.mdx +1 -1
  77. package/docs/zh/community/blog/v2-release-note.mdx +1 -1
  78. package/docs/zh/components/enable-bff.mdx +19 -2
  79. package/docs/zh/components/extend-bff-function.mdx +5 -0
  80. package/docs/zh/components/init-app.mdx +0 -1
  81. package/docs/zh/components/init-rspack-app.mdx +0 -1
  82. package/docs/zh/components/other-plugins.mdx +0 -0
  83. package/docs/zh/components/ssr-monitor.mdx +3 -0
  84. package/docs/zh/configure/app/auto-load-plugin.mdx +4 -0
  85. package/docs/zh/configure/app/output/ssg.mdx +49 -139
  86. package/docs/zh/configure/app/plugins.mdx +2 -2
  87. package/docs/zh/configure/app/tools/esbuild.mdx +1 -1
  88. package/docs/zh/configure/app/tools/swc.mdx +1 -1
  89. package/docs/zh/configure/app/tools/tailwindcss.mdx +1 -1
  90. package/docs/zh/guides/_meta.json +0 -5
  91. package/docs/zh/guides/advanced-features/_meta.json +3 -8
  92. package/docs/zh/guides/advanced-features/bff/_meta.json +1 -1
  93. package/docs/zh/guides/advanced-features/bff/extend-server.mdx +156 -0
  94. package/docs/zh/guides/advanced-features/bff/frameworks.mdx +51 -117
  95. package/docs/zh/guides/advanced-features/bff/function.mdx +69 -59
  96. package/docs/zh/guides/advanced-features/bff/sdk.mdx +27 -36
  97. package/docs/zh/guides/advanced-features/build-performance.mdx +6 -21
  98. package/docs/zh/guides/advanced-features/page-performance/_meta.json +1 -0
  99. package/docs/zh/guides/advanced-features/rspack-start.mdx +8 -17
  100. package/docs/zh/guides/basic-features/_meta.json +31 -9
  101. package/docs/zh/guides/basic-features/alias.mdx +5 -11
  102. package/docs/zh/guides/basic-features/css/_meta.json +1 -0
  103. package/docs/zh/guides/basic-features/css/css-in-js.mdx +34 -0
  104. package/docs/zh/guides/basic-features/css/css.mdx +25 -0
  105. package/docs/zh/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +3 -64
  106. package/docs/zh/guides/basic-features/data/data-fetch.mdx +96 -211
  107. package/docs/zh/guides/basic-features/data/data-write.mdx +54 -55
  108. package/docs/zh/guides/basic-features/debug/_meta.json +1 -0
  109. package/docs/zh/guides/basic-features/debug/rsdoctor.mdx +57 -0
  110. package/docs/zh/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +1 -1
  111. package/docs/zh/guides/basic-features/env-vars.mdx +1 -1
  112. package/docs/zh/guides/basic-features/render/_meta.json +1 -0
  113. package/docs/zh/guides/basic-features/render/ssg.mdx +210 -0
  114. package/docs/zh/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +16 -26
  115. package/docs/zh/guides/basic-features/render/ssr.mdx +309 -0
  116. package/docs/zh/guides/{advanced-features/ssr/stream.mdx → basic-features/render/streaming-ssr.mdx} +22 -37
  117. package/docs/zh/guides/basic-features/routes.mdx +251 -237
  118. package/docs/zh/guides/basic-features/static-assets/_meta.json +1 -0
  119. package/docs/zh/guides/basic-features/static-assets.mdx +3 -7
  120. package/docs/zh/guides/basic-features/testing/_meta.json +1 -0
  121. package/docs/zh/guides/basic-features/testing/cypress.mdx +95 -0
  122. package/docs/zh/guides/basic-features/testing/jest.mdx +148 -0
  123. package/docs/zh/guides/basic-features/testing/playwright.mdx +112 -0
  124. package/docs/zh/guides/basic-features/testing/vitest.mdx +100 -0
  125. package/docs/zh/guides/concept/entries.mdx +6 -3
  126. package/docs/zh/guides/deprecated.md +4 -0
  127. package/docs/zh/guides/get-started/quick-start.mdx +1 -1
  128. package/docs/zh/guides/get-started/tech-stack.mdx +8 -8
  129. package/docs/zh/guides/topic-detail/_meta.json +0 -6
  130. package/docs/zh/guides/topic-detail/generator/create/config.mdx +0 -10
  131. package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -1
  132. package/docs/zh/plugin/_meta.json +19 -0
  133. package/docs/zh/plugin/cli-plugins/_meta.json +1 -0
  134. package/docs/zh/plugin/cli-plugins/plugin-bff.mdx +5 -0
  135. package/docs/zh/plugin/cli-plugins/plugin-ssg.mdx +5 -0
  136. package/docs/zh/{guides/rsbuild-plugins → plugin/cli-plugins}/plugin-swc.mdx +7 -0
  137. package/docs/zh/plugin/cli-plugins/plugin-tailwind.mdx +5 -0
  138. package/docs/zh/plugin/cli-plugins.mdx +6 -0
  139. package/docs/zh/{guides/advanced-features/rsbuild-plugin.mdx → plugin/introduction.mdx} +38 -13
  140. package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/extend.mdx +1 -1
  141. package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/implement.mdx +3 -3
  142. package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/plugin-api.mdx +2 -2
  143. package/docs/zh/plugin/rsbuild-plugins/_meta.json +1 -0
  144. package/docs/zh/plugin/rsbuild-plugins.mdx +4 -0
  145. package/docs/zh/tutorials/first-app/c03-css.mdx +1 -1
  146. package/i18n.json +42 -6
  147. package/package.json +7 -6
  148. package/rspress.config.ts +1 -58
  149. package/src/components/Footer/index.tsx +1 -1
  150. package/src/pages/index.tsx +0 -1
  151. package/docs/en/apis/app/hooks/api/api.mdx +0 -80
  152. package/docs/en/apis/app/hooks/api/app.mdx +0 -12
  153. package/docs/en/apis/app/hooks/config/storybook.mdx +0 -37
  154. package/docs/en/guides/advanced-features/bff/type.mdx +0 -46
  155. package/docs/en/guides/advanced-features/eslint.mdx +0 -148
  156. package/docs/en/guides/advanced-features/ssg.mdx +0 -116
  157. package/docs/en/guides/advanced-features/ssr/_meta.json +0 -1
  158. package/docs/en/guides/advanced-features/ssr/index.mdx +0 -23
  159. package/docs/en/guides/advanced-features/ssr/stream.mdx +0 -248
  160. package/docs/en/guides/advanced-features/ssr/usage.mdx +0 -341
  161. package/docs/en/guides/advanced-features/ssr.mdx +0 -555
  162. package/docs/zh/apis/app/hooks/api/api.mdx +0 -81
  163. package/docs/zh/apis/app/hooks/api/app.mdx +0 -12
  164. package/docs/zh/apis/app/hooks/config/storybook.mdx +0 -38
  165. package/docs/zh/guides/advanced-features/bff/type.mdx +0 -46
  166. package/docs/zh/guides/advanced-features/eslint.mdx +0 -152
  167. package/docs/zh/guides/advanced-features/ssg.mdx +0 -116
  168. package/docs/zh/guides/advanced-features/ssr/_meta.json +0 -1
  169. package/docs/zh/guides/advanced-features/ssr/index.mdx +0 -23
  170. package/docs/zh/guides/advanced-features/ssr/usage.mdx +0 -329
  171. /package/docs/en/guides/advanced-features/{bff/index.mdx → bff.mdx} +0 -0
  172. /package/docs/en/guides/advanced-features/{code-split.mdx → page-performance/code-split.mdx} +0 -0
  173. /package/docs/en/guides/advanced-features/{inline-assets.mdx → page-performance/inline-assets.mdx} +0 -0
  174. /package/docs/en/guides/advanced-features/{optimize-bundle.mdx → page-performance/optimize-bundle.mdx} +0 -0
  175. /package/docs/en/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
  176. /package/docs/en/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
  177. /package/docs/en/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
  178. /package/docs/en/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
  179. /package/docs/en/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
  180. /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/_meta.json +0 -0
  181. /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook-list.mdx +0 -0
  182. /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook.mdx +0 -0
  183. /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/introduction.mdx +0 -0
  184. /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/lifecycle.mdx +0 -0
  185. /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/relationship.mdx +0 -0
  186. /package/docs/en/{guides → plugin}/rsbuild-plugins/plugin-esbuild.mdx +0 -0
  187. /package/docs/zh/guides/advanced-features/{bff/index.mdx → bff.mdx} +0 -0
  188. /package/docs/zh/guides/advanced-features/{code-split.mdx → page-performance/code-split.mdx} +0 -0
  189. /package/docs/zh/guides/advanced-features/{inline-assets.mdx → page-performance/inline-assets.mdx} +0 -0
  190. /package/docs/zh/guides/advanced-features/{optimize-bundle.mdx → page-performance/optimize-bundle.mdx} +0 -0
  191. /package/docs/zh/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -0
  192. /package/docs/zh/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
  193. /package/docs/zh/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
  194. /package/docs/zh/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
  195. /package/docs/zh/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
  196. /package/docs/zh/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
  197. /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/_meta.json +0 -0
  198. /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook-list.mdx +0 -0
  199. /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook.mdx +0 -0
  200. /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/introduction.mdx +0 -0
  201. /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/lifecycle.mdx +0 -0
  202. /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/relationship.mdx +0 -0
  203. /package/docs/zh/{guides → plugin}/rsbuild-plugins/plugin-esbuild.mdx +0 -0
@@ -1,46 +0,0 @@
1
- ---
2
- sidebar_position: 2
3
- title: 函数写法 & 框架写法
4
- ---
5
- # 函数写法 & 框架写法
6
-
7
- 运行时框架支持也是 **BFF** 中重要的一环。Modern.js 支持通过插件扩展 BFF 的运行时框架,并提供了一系列内置插件,开发者可以直接使用对应框架的约定和生态。
8
-
9
- 插件中兼容了这些框架大部分的规范,每一种框架都需要提供两类扩展写法 BFF 函数的方式,分别是**函数写法**和**框架写法**。
10
-
11
- :::note
12
- 当前 `api/` 目录结构是否为框架写法由对应的插件决定,Modern.js 并不关心。
13
-
14
- :::
15
-
16
- ## 函数写法
17
-
18
- 当插件认为当前为函数写法时,必须支持在 `api/_app.ts` 中编写中间件,用来扩展 BFF 函数。
19
-
20
- Modern.js 会收集 `api/_app.ts` 中的中间件,并传递给插件,由插件将中间件注入运行时,例如:
21
-
22
- ```ts
23
- import { hook } from '@modern-js/runtime/server';
24
-
25
- export default hook(({ addMiddleware }) => {
26
- addMiddleware(myMiddleware);
27
- });
28
- ```
29
-
30
- :::note
31
- 不同插件的中间件的写法不一定相同,详情可见[运行时框架](/guides/advanced-features/bff/frameworks)。
32
-
33
- :::
34
-
35
- ## 框架写法
36
-
37
- 框架写法是一种使用框架结构来扩展 BFF 函数的方式。和函数写法相比,框架写法虽然能够利用更多框架的结构,在复杂场景下让整个 BFF Server 更加清晰,但也相的更加复杂,需要关心更多框架层面的内容。
38
-
39
- 框架写法中,所有的 BFF 函数都需要写在 `api/lambda/` 目录下,并且无法使用钩子文件 `_app.[tj]s`。
40
-
41
- 多数情况下,函数写法就能覆盖大多数 BFF 函数的定制需求。只有当你的项目服务端逻辑比较复杂,代码需要分层,或者需要使用更多框架的元素时,才需要使用框架写法。
42
-
43
- :::note
44
- 不同插件框架写法的目录结构不一定相同,详情可见[运行时框架](/guides/advanced-features/bff/frameworks)。
45
-
46
- :::
@@ -1,152 +0,0 @@
1
- ---
2
- sidebar_position: 8
3
- ---
4
-
5
- # ESLint 规则集
6
-
7
- {/* 参考 [实战教程 - 确认编程环境](../handbook/c03-ide/3.1-setting-up) 确保本地 IDE 环境正常。 */}
8
-
9
- **Modern.js ESLint 规则集**是全量的 **ESLint** 规则集合,包含 `@modern-js` (对于 Node.js 项目的 Lint 规则)和 `@modern-js-app`(对于前端项目的 Lint 规则)。
10
-
11
- 下面以具体问题介绍更多 ESLint 用法。
12
-
13
- ## Q: 如何处理 Lint
14
-
15
- ### 实时自动修复
16
-
17
- 多数问题会被 ESLint 规则的自动修复功能或 [Prettier](https://prettier.io/) 的代码格式化功能(已被集成到 ESLint 里)自动解决,开发者不需要关心问题的细节和解决方式。
18
-
19
- :::info
20
- 主要在 IDE 保存文件的环节执行这种自动修复,少数漏网之鱼会在提交代码环节被自动修复。
21
-
22
- :::
23
-
24
- ### 批量自动修复
25
-
26
- 在少数情况下,比如旧项目迁移的时候,可以执行以下命令,批量修复和检查所有文件:
27
-
28
- ```bash
29
- pnpm run lint:error
30
- ```
31
-
32
- ### 人工修复
33
-
34
- 对于无法自动修复的问题,可以在 IDE 里点击问题提示框里的规则链接,打开这条规则的文档,查看问题的解释和解决方案。
35
-
36
- ### 声明例外情况
37
-
38
- 目前阶段,有些规则并不能做到足够智能,多数情况下会有很大收益,在少数情况下也许不适用。但如果为了这些少数情况就把整个规则关掉或改掉,得不偿失。
39
-
40
- 这种情况下可以用 [eslint-disable](https://eslint.org/docs/user-guide/configuring/rules#disabling-rules) 注释,对符合**少数情况**的代码块做标注,声明这里是一个例外,应该忽略。比如:
41
-
42
- ```js
43
- /* eslint-disable filenames/match-exported */
44
- ...
45
- /* eslint-enable filenames/match-exported */
46
- ```
47
-
48
- :::info
49
- 在 VS Code 编辑器里输入 eslint,会自动出现关于 "eslint-disable" 的提示框,选择提示选项生成对应注释对。
50
-
51
- :::
52
-
53
- 【Modern.js ESLint 规则集】要求 [eslint-disable](https://eslint.org/docs/user-guide/configuring/rules#disabling-rules) 必须成对使用,必须明确表达要影响的范围,以及在这个范围内明确表达要禁用什么规则,目的是让**例外**有明确的、最小化的范围,避免 [eslint-disable](https://eslint.org/docs/user-guide/configuring/rules#disabling-rules) 被滥用,导致不属于例外的代码也被禁用了规则。
54
-
55
- ## Q: 如何自定义 ESLint 规则
56
-
57
- ### 仓库根目录下 `package.json` 里的 "eslintConfig" 字段
58
-
59
- 这个地方是整个仓库的默认 ESLint 配置,是针对纯 Node.js 代码(只能在 Node.js 里运行)设计的。
60
-
61
- 如果项目在某些规则上确实有特殊要求或不可避免的兼容问题(不是例外),可以在这里增加规则配置。该配置会优先于默认的【Modern.js ESLint 规则集】,比如:
62
-
63
- ```json
64
- "eslintConfig": {
65
- "extends": [
66
- "@modern-js"
67
- ],
68
- "rules": {
69
- "filenames/match-exported": "off"
70
- }
71
- },
72
-
73
- ```
74
-
75
- ### `src/.eslintrc.js` 文件
76
-
77
- Modern.js Framework、Modern.js Module 的源代码目录里都会默认有这个配置文件,是针对 Universal JS 代码设计的。
78
-
79
- :::info
80
- Universal JS 代码是既能浏览器端也能在服务器端运行的代码。
81
-
82
- :::
83
-
84
- 如果项目在某些规则上确实有特殊要求或不可避免的兼容问题(不是例外),可以在这里增加规则配置,该配置会优先于默认的【Modern.js ESLint 规则集】,比如:
85
-
86
- ```js
87
- // eslint-disable-next-line import/no-commonjs
88
- module.exports = {
89
- root: true,
90
- extends: ['@modern-js-app'],
91
- parserOptions: {
92
- tsconfigRootDir: __dirname,
93
- project: ['../tsconfig.json'],
94
- },
95
- rules: {
96
- 'filenames/match-exported': 'off',
97
- },
98
- };
99
- ```
100
-
101
- 如果有需要,还可以继续在不同的子目录里增加 `.eslintrc.js` 文件,针对这个子目录里的代码做特殊配置:
102
-
103
- ```js
104
- module.exports = {
105
- rules: {
106
- 'filenames/match-exported': 'off',
107
- },
108
- };
109
- ```
110
-
111
- :::tip 提示
112
- 注意:没有必要使用 `extends` 字段,会自动继承父目录的配置。
113
-
114
- :::
115
-
116
- ### package.json 里的 `eslintIgnore` 字段
117
-
118
- 把包含 `.js`、`.jsx`、`.ts`、`.tsx` 文件、但不需要做代码检查和自动修复的目录,添加到 `eslintIgnore` 里,可以优化 ESLint 检查的速度,比如:
119
-
120
- ```json
121
- "eslintIgnore": [
122
- "node_modules",
123
- "dist",
124
- "output"
125
- ],
126
- ```
127
-
128
- ## Q: 如何升级 ESLint 插件的版本
129
-
130
- 只要不是 Major 版本的变化(不符合 [Semver](https://semver.org/) 规则的 `^` 符号),就可以直接在业务项目的 `package.json` 里指定这个依赖,删除 Lock 文件(或尝试手动删除 Lock 文件中这个包名的内容),执行 `pnpm install` 重新安装依赖并且生成新的 Lock 文件。
131
-
132
- 做完这些操作之后,在业务项目的 `./node_modules` 目录里,这个插件应该只存在一份,并且升级到了你指定的版本。
133
-
134
- :::tip 提示
135
- - Major 版本就是主版本号。更多信息,请阅读 [Semantic Versioning](https://semver.org/#summary)。
136
- - 所有被 Modern.js 封装的上游项目(比如 ESLint、[ESLint 插件](https://eslint.org/docs/user-guide/configuring/plugins#plugins)、[React Router](https://reactrouter.com/) 等),也都可以这样升级。
137
- - Modern.js 也会在每次发版中尽量及时的升级这些上游依赖。
138
- - Major 版本的升级需要由 Modern.js 来发版。
139
-
140
- :::
141
-
142
- ## Q: WebStorm 有时候会报 ESLint 错误
143
-
144
- 由于 WebStorm 认为 ESLint 执行目录是根据 `.eslintrc` 文件来决定的。因此 `src/.eslintrc` 文件位置的放置会导致 `tsconfig.json` 文件指定的位置(项目根目录下)在 `src/` 目录下找不到。
145
-
146
- 此时需要手动配置一下:
147
-
148
- ```json
149
- --parser-options=project:../tsconfig.json
150
- ```
151
-
152
- ![webstorm-lint-error](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/webstorm-lint-error.png)
@@ -1,116 +0,0 @@
1
- ---
2
- sidebar_position: 5
3
- ---
4
-
5
- # 静态站点生成
6
-
7
- SSG(Static Site Generation)是一种基于数据与模板,在构建时渲染完整静态网页的技术解决方案。
8
-
9
- 我们首先需要执行 `pnpm run new` 启用 SSG 功能:
10
-
11
- ```bash
12
- ? 请选择你想要的操作 启用可选功能
13
- ? 请选择功能名称 启用「SSG」功能
14
- ```
15
-
16
- 执行命令后,在 `modern.config.ts` 中注册 SSG 插件:
17
-
18
- ```ts title="modern.config.ts"
19
- import { ssgPlugin } from '@modern-js/plugin-ssg';
20
-
21
- export default defineConfig({
22
- output: {
23
- ssg: true,
24
- },
25
- plugins: [..., ssgPlugin()],
26
- });
27
- ```
28
-
29
- SSG 在**约定式路由**和**自控式路由**下的使用方式不同。
30
-
31
- ### 在约定式路由中使用
32
-
33
- **约定式路由**中, Modern.js 根据入口下的文件结构生成路由,因此框架能够收集完整的路由信息。
34
-
35
- 例如,以下是一个使用约定式路由的项目目录结构:
36
-
37
- ```
38
- .
39
- ├── src
40
- │ └── routes
41
- │ ├── layout.tsx
42
- │ ├── page.tsx
43
- │ └── user
44
- │ ├── layout.tsx
45
- │ ├── page.tsx
46
- │ └── profile
47
- │ └── page.tsx
48
- ```
49
-
50
- 上述文件目录将会生成以下三条路由:
51
-
52
- - `/`
53
- - `/user`
54
- - `/user/profile`
55
-
56
- :::note
57
- 如果还不了解约定式路由的规则,可以先查看[路由方案](/guides/basic-features/routes)。
58
-
59
- :::
60
-
61
- 在 `src/routes/page.tsx` 中添加组件代码:
62
-
63
- ```jsx title="src/routes/page.tsx"
64
- export default () => {
65
- return <div>Index Page</div>;
66
- };
67
- ```
68
-
69
- SSG 也是在 Node.js 环境渲染页面,因此我们可以在**开发阶段开启 SSR**,提前在暴露代码问题,验证 SSG 渲染效果:
70
-
71
- ```ts title="modern.config.ts"
72
- export default defineConfig({
73
- server: {
74
- ssr: process.env.NODE_ENV === 'development',
75
- }
76
- }
77
- ```
78
-
79
- 在项目根路径下执行 `pnpm run dev` 命令,查看 `dist/` 目录,此时只生成一个 HTML 文件 `main/index.html`。
80
-
81
- 在项目根路径下执行 `pnpm run build` 命令,构建完成后,查看 `dist/` 目录,此时生成 `main/index.html`、`main/user/index.html` 和 `main/user/profile/index.html` 三个 HTML 文件,内容分别对应上述三条路由。
82
-
83
- **约定式路由**中的每一条路由,都会生成一个单独的 HTML 文件。查看 `main/index.html`,可以发现包含 `Index Page` 的文本内容,这正是 SSG 的效果。
84
-
85
- 执行 `pnpm run serve` 启动项目后,访问页面,在浏览器我们工具的 Network 窗口,查看请求返回的文档,文档包含组件渲染后的完整页面内容。
86
-
87
- ### 在自控式路由中使用
88
-
89
- **自控式路由**是通过组件代码定义路由,需要应用运行起来才能获取准确的路由信息。因此,无法开箱即用的使用 SSG 功能。此时需要用户提前告知 Modern.js 框架,哪些路由需要开启 SSG 功能。
90
-
91
- 例如有以下代码,包含多条路由,设置 `output.ssg` 为 `true` 时,默认只会渲染入口路由即 `/`:
92
-
93
- import SelfRouteExample from '@site-docs/components/self-route-example';
94
-
95
- <SelfRouteExample />
96
-
97
- 如果我们希望同时开启 `/about` 的 SSG 功能,可以配置 `output.ssg`,告知 Modern.js 开启指定路由的 SSG 功能。
98
-
99
- ```ts title="modern.config.ts"
100
- export default defineConfig({
101
- output: {
102
- ssg: {
103
- routes: ['/', '/about'],
104
- },
105
- },
106
- });
107
- ```
108
-
109
- 执行 `pnpm run build` 与 `pnpm run serve` 后,访问 `http://localhost:8080/about`,在 Preview 视图中可以看到页面已经完成渲染。
110
-
111
- 查看构建产物文件,可以看到 `dist/` 目录中,新增了一个 `main/about/index.html` 文件。
112
-
113
- :::info
114
- 以上仅介绍了单入口的情况,更多相关内容可以查看 [API 文档](/configure/app/output/ssg)。
115
-
116
- :::
@@ -1 +0,0 @@
1
- ["usage", "stream", "cache"]
@@ -1,23 +0,0 @@
1
- # 服务端渲染
2
-
3
- 通过在服务器端将网页的 HTML 内容渲染成完整的网页(Server-Side Rendering,简称 SSR),然后将生成的网页发送到客户端,客户端只需要显示网页即可,不需要再进行额外的渲染。
4
-
5
- 它主要的优势在于
6
-
7
- - 提高首屏加载速度:SSR 可以在服务器端生成完整的网页,客户端只需要下载网页内容即可,不需要再进行额外的渲染,从而提高了首屏加载速度。
8
- - 提高用户体验:SSR 可以提高网页的响应速度,从而提高用户体验。
9
- - 有利于 SEO:SSR 可以生成完整的 HTML 内容,搜索引擎可以直接索引 HTML 内容,从而提高网站的排名。
10
-
11
- 如果你有以下场景的需求,开发者可以考虑使用 SSR 来渲染你的页面:
12
-
13
- 1. 对首屏加载速度要求较高的网站,如电商网站、新闻网站等。
14
- 2. 对用户体验要求较高的网站,如社交网站、游戏网站等。
15
- 3. 对 SEO 要求较高的网站,如企业官网、博客等。
16
-
17
- 在 Modern.js 中,SSR 也是开箱即用的。开发者无需为 SSR 编写复杂的服务端逻辑,也无需关心 SSR 的运维,或是创建单独的服务。
18
-
19
- 除了开箱即用的 SSR 服务,为了保证开发者的开发体验,我们还具备:
20
-
21
- - 完备的 SSR 降级策略,保证页面能够安全运行。
22
- - 自动分割子路由,按需加载,减少首屏资源体积。
23
- - 内置缓存系统,解决服务端负载高的问题。
@@ -1,329 +0,0 @@
1
- ---
2
- sidebar_position: 1
3
- title: 基础使用
4
- ---
5
-
6
- # 基础使用
7
-
8
- 启用 SSR 非常简单,只需要设置 [`server.ssr`](/configure/app/server/ssr) 为 `true` 即可:
9
-
10
- ```ts title="modern.config.ts"
11
- import { defineConfig } from '@modern-js/app-tools';
12
-
13
- export default defineConfig({
14
- server: {
15
- ssr: true,
16
- },
17
- });
18
- ```
19
-
20
- ## SSR 时的数据获取
21
-
22
- Modern.js 中提供了 Data Loader,方便开发者在 SSR、CSR 下同构地获取数据。每个路由模块,如 `layout.tsx` 和 `page.tsx` 都可以定义自己的 Data Loader:
23
-
24
- ```ts title="src/routes/page.data.ts"
25
- export const loader = () => {
26
- return {
27
- message: 'Hello World',
28
- };
29
- };
30
- ```
31
-
32
- 在组件中可以通过 Hooks API 的方式获取 `loader` 函数返回的数据:
33
-
34
- ```tsx
35
- import { useLoaderData } from '@modern-js/runtime/router';
36
- export default () => {
37
- const data = useLoaderData();
38
- return <div>{data.message}</div>;
39
- };
40
- ```
41
-
42
- Modern.js 打破传统的 SSR 开发模式,提供了用户无感的 SSR 开发体验。并且提供了优雅的降级处理,一旦 SSR 请求失败,会自动降级在浏览器端重新发起请求。
43
-
44
- 不过,开发者仍然需要关注数据的兜底处理,例如 `null` 值或不符合预期的数据返回。避免在 SSR 时产生 React 渲染错误或是返回凌乱的渲染结果。
45
-
46
- :::info 补充信息
47
-
48
- 1. 当以客户端路由的方式请求页面时,Modern.js 会发送一个 HTTP 请求,服务端接收到请求后执行页面对应的 Data Loader 函数,然后将执行结果作为请求的响应返回浏览器。
49
-
50
- 2. 使用 Data Loader 时,数据获取发生在渲染前,Modern.js 也仍然支持在组件渲染时获取数据。更多相关内容可以查看[数据获取](/guides/basic-features/data/data-fetch)。
51
-
52
- :::
53
-
54
- ## 保持渲染一致
55
-
56
- 有些业务中,UI 展示会和用户设备有关,例如 [UA](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) 信息。如果处理不够仔细,此时很有可能出现不符合预期的渲染结果。
57
-
58
- 这里通过一个例子,演示当 SSR 与 CSR 渲染不一致时出现的问题,在组件中添加以下代码:
59
-
60
- ```tsx
61
- {
62
- typeof window !== 'undefined' ? <div>browser content</div> : null;
63
- }
64
- ```
65
-
66
- 启动应用后,访问页面,会发现浏览器控制台抛出警告信息:
67
-
68
- ```sh
69
- Warning: Expected server HTML to contain a matching <div> in <div>.
70
- ```
71
-
72
- 这是 React hydrate 结果与 SSR 渲染结果不一致造成的。虽然当前页面表现正常,但在复杂应用中,很有可能因此出现 DOM 层级混乱、样式混乱等问题。
73
-
74
- :::info
75
- 关于 hydrate (注水)逻辑请参考[这里](https://zh-hans.react.dev/reference/react-dom/hydrate)。
76
-
77
- :::
78
-
79
- 应用需要保持 SSR 与 CSR 渲染结果的一致性,如果存在不一致的情况,说明这部分内容无需在 SSR 中进行渲染。Modern.js 为这类在 SSR 中不需要渲染的内容提供 [`<NoSSR>` 工具组件](/apis/app/runtime/core/use-runtime-context):
80
-
81
- ```ts
82
- import { NoSSR } from '@modern-js/runtime/ssr';
83
- ```
84
-
85
- 在不需要进行 SSR 的元素外部,用 `NoSSR` 组件包裹:
86
-
87
- ```tsx
88
- <NoSSR>
89
- <div>client content</div>
90
- </NoSSR>
91
- ```
92
-
93
- 修改代码后,刷新页发现之前的 Waring 消失。打开浏览器开发者工具的 Network 窗口,查看返回的 HTML 文档是不包含 `NoSSR` 组件包裹的内容的。
94
-
95
- :::info 补充信息
96
- [`useRuntimeContext`](/apis/app/runtime/core/use-runtime-context) 可以获取完整的请求信息,可以利用它保证 SSR 与 CSR 的渲染结果一致。
97
-
98
- :::
99
-
100
- ## 关注内存泄漏
101
-
102
- :::warning 警告
103
- 在 SSR 场景下,开发者需要特别关注内存泄露问题,即使是微小的内存泄露,在大量的访问后也会对服务造成影响。
104
-
105
- :::
106
-
107
- SSR 时,浏览器的每次请求,都会触发服务端重新执行一次组件渲染逻辑。所以,需要避免在全局定义任何可能不断增长的数据结构,或在全局进行事件订阅,或创建不会被销毁的流。
108
-
109
- 例如以下代码,使用 [redux-observable](https://redux-observable.js.org/) 时,习惯了 CSR 的开发者通常会在组件中这样编码:
110
-
111
- ```tsx
112
- /* 代码仅作为示例,不可运行 */
113
- import { createEpicMiddleware, combineEpics } from 'redux-observable';
114
-
115
- const epicMiddleware = createEpicMiddleware();
116
- const rootEpic = combineEpics();
117
-
118
- export default function Test() {
119
- epicMiddleware.run(rootEpic);
120
- return <div>Hello Modern.js</div>;
121
- }
122
- ```
123
-
124
- 在组件外层创建 Middleware 实例 `epicMiddleware`,并在组件内部调用 `epicMiddleware.run`。
125
-
126
- 在浏览器端,这段代码不会造成任何问题,但是在 SSR 时,Middleware 实例会一直无法被销毁。每次渲染组件,调用 `epicMiddleware.run(rootEpic)` 时,都会在内部添加新的事件绑定,导致整个对象不断变大,最终对应用性能造成影响。
127
-
128
- CSR 中这类问题不易被发觉,因此从 CSR 切换到 SSR 时,如果不确定应用是否存在这类隐患,可以对应用进行压测。
129
-
130
- ## 收敛服务端数据
131
-
132
- 为了使浏览器端能够直接使用 SSR 阶段请求的数据,Modern.js 会将渲染过程中收集的数据与状态注入到 HTML 内。但是,CSR 应用常常存在接口数据量大、组件状态未收敛的情况,这时如果直接使用 SSR,渲染得到的 HTML 体积可能会存在过大的问题。此时,SSR 不仅无法为应用带来用户体验上的提升,反而可能起到相反的作用。
133
-
134
- 因此,使用 SSR 时,**开发者需要为应用做合理的瘦身**:
135
-
136
- 1. 关注首屏,SSR 中可以只请求首屏需要的数据,并在浏览器端渲染剩余的部分。
137
- 2. 将与渲染无关的数据,从接口返回数据中剔除。
138
-
139
- ## Serverless Pre-render
140
-
141
- :::warning
142
- x.43.0+ 已废弃,请使用 [SSR Cache](guides/advanced-features/ssr/cache) 替代
143
- :::
144
-
145
- Modern.js 提供 Serverless Pre-rendering (SPR) 这一特性来提升 SSR 性能。
146
-
147
- SPR 利用预渲染与缓存技术,为 SSR 页面提供静态 Web 的响应性能。它让 SSR 应用拥有静态 Web 页面的响应速度与稳定性,同时还能保持数据的动态更新。
148
-
149
- 在 Modern.js 中使用 SPR 非常简单,只需要在组件中新增 `PreRender` 组件,该组件所在的页面就会自动开启 SPR。
150
-
151
- 这里模拟一个使用 `useLoaderData` API 的组件,Data Loader 中的请求需要消耗 2s 时间。
152
-
153
- ```tsx title="page.data.ts"
154
- export const loader = async () => {
155
- await new Promise((resolve, reject) => {
156
- setTimeout(() => {
157
- resolve(null);
158
- }, 2000);
159
- });
160
-
161
- return {
162
- message: 'Hello Modern.js',
163
- };
164
- };
165
- ```
166
-
167
- ```tsx title="page.tsx"
168
- import { useLoaderData } from '@modern-js/runtime/router';
169
-
170
- export default () => {
171
- const data = useLoaderData();
172
- return <div>{data?.message}</div>;
173
- };
174
- ```
175
-
176
- 执行 `dev` 命令后,打开页面,可以明显的察觉到页面需要等到 2s 后才返回。
177
-
178
- 接下来使用 `PreRender` 组件来进行优化,该组件可以直接从 `@modern-js/runtime/ssr` 中导出:
179
-
180
- ```ts
181
- import { PreRender } from '@modern-js/runtime/ssr';
182
- ```
183
-
184
- 在路由组件内使用 `PreRender` 组件,并设置参数 `interval`,用于表示该次渲染结果的过期时间为 5s:
185
-
186
- ```tsx
187
- <PreRender interval={5} />
188
- ```
189
-
190
- 修改后,执行 `pnpm run build && pnpm run serve` 启动应用,并打开页面。
191
-
192
- 首次打开时,和之前的渲染并没有什么不同,同样存在 2s 延迟。点击刷新,页面瞬间打开,但此时,页面数据并没有因为刷新发生变化,这是因为缓存还没有过期。
193
-
194
- 等待 5s,重新刷新页面,页面的数据仍然没有变化。再一次刷新页面数据发生变化,但是页面仍然几乎是瞬间响应的。
195
- 这是因为在之前的请求时,SPR 已经在后台异步获取了新的渲染结果,本次请求到的页面是已经缓存在服务器中的版本。
196
-
197
- 可以想象,当 `interval` 设置为 1 时,用户可以在感知到实时数据的同时,拥有静态页面的响应体验。
198
-
199
- :::info 补充信息
200
- `PreRender` 的详细使用可以参考[这里](/apis/app/runtime/ssr/pre-render)。
201
-
202
- :::
203
-
204
- ## Treeshaking
205
-
206
- 开启 SSR 时,Modern.js 会用相同的入口,构建出 SSR Bundle 和 CSR Bundle 两份产物。因此,在 SSR Bundle 中存在 Web API,或是在 CSR Bundle 中存在 Node API 时,都可能导致运行出错。
207
-
208
- 在组件中引入 Web API,通常情况下是要做一些全局监听,或是获取浏览器相关的数据,例如:
209
-
210
- ```tsx
211
- document.addEventListener('load', () => {
212
- console.log('document load');
213
- });
214
- const App = () => {
215
- return <div>Hello World</div>;
216
- };
217
- export default App;
218
- ```
219
-
220
- 在组件文件中引入 Node API,通常情况下是因为使用了 `useLoader`,例如:
221
-
222
- ```ts
223
- import fse from 'fs-extra';
224
- import { useLoader } from '@modern-js/runtime'
225
-
226
- const App = () => {
227
- const { data } = useLoader(async () => {
228
- const file = fse.readFileSync('./myfile');
229
- return {
230
- ...
231
- };
232
- })
233
-
234
- return <div>Hello World</div>;
235
- };
236
- export default App;
237
- ```
238
-
239
- ### 环境变量区分
240
-
241
- 对于第一种情况,我们可以直接使用 Modern.js 内置的环境变量 `MODERN_TARGET` 进行判断,在构建时删除无用代码:
242
-
243
- ```ts
244
- if (process.env.MODERN_TARGET === 'browser') {
245
- document.addEventListener('load', () => {
246
- console.log('document load');
247
- });
248
- }
249
- ```
250
-
251
- 开发环境打包后,SSR 产物和 CSR 产物会被编译成以下内容。因此 SSR 环境中不会再因为 Web API 报错:
252
-
253
- ```ts
254
- // SSR 产物
255
- if (false) {
256
- }
257
-
258
- // CSR 产物
259
- if (true) {
260
- document.addEventListener('load', () => {
261
- console.log('document load');
262
- });
263
- }
264
- ```
265
-
266
- :::note
267
- 更多内容可以查看[环境变量](/guides/basic-features/env-vars)。
268
- :::
269
-
270
- ### 文件后缀区分
271
-
272
- 但例如第二种情况,在代码中引入了 `fs-extra`,它内部有使用了 Node API 的副作用,如果直接引用到组件中,会造成 CSR 加载报错。
273
-
274
- 环境变量的方式并不能在这种情况下生效,Modern.js 也支持通过 `.node.` 后缀的文件来区分 SSR Bundle 和 CSR Bundle 产物的打包文件。
275
-
276
- 可以创建同名的 `.ts` 和 `.node.ts` 文件做一层代理:
277
-
278
- ```ts title="compat.ts"
279
- export const readFileSync: any = () => {};
280
- ```
281
-
282
- ```ts title="compat.node.ts"
283
- export { readFileSync } from 'fs-extra';
284
- ```
285
-
286
- 在文件中直接引入 `./compat`,此时 SSR 环境下会优先使用 `.node.ts` 后缀的文件,CSR 环境下会使用 `.ts` 后缀的文件。
287
-
288
- ```ts title="App.tsx"
289
- import { readFileSync } from './compat'
290
-
291
- export const loader = () => {
292
- const file = readFileSync('./myfile');
293
- return {
294
- ...
295
- };
296
- };
297
- ```
298
-
299
- ### 独立文件
300
-
301
- 上述两种方式,都会为开发者带来一些心智负担。在真实的业务中,我们发现大多数的 Node / Web 代码混用都出现在数据请求中。
302
-
303
- 因此,Modern.js 基于[嵌套路由](/guides/basic-features/routes)开发设计了[更简单的方案](/guides/basic-features/data/data-fetch)来分离 CSR 和 SSR 的代码。
304
-
305
- 我们可以通过独立文件来分离**数据请求**与**组件代码**。在 `routes/page.tsx` 中编写组件逻辑,在 `routes/page.data.ts` 中编写数据请求逻辑。
306
-
307
- ```ts title="routes/page.tsx"
308
- export default Page = () => {
309
- return <div>Hello World<div>
310
- }
311
- ```
312
-
313
- ```ts title="routes/page.data.tsx"
314
- import fse from 'fs-extra';
315
- export const loader = () => {
316
- const file = fse.readFileSync('./myfile');
317
- return {
318
- ...
319
- };
320
- }
321
- ```
322
-
323
- ## 接口请求
324
-
325
- 在 SSR 中发起接口请求时,开发者有时自己封装了同构的请求工具。部分接口需要传递用户 Cookie,开发者可以通过 [`useRuntimeContext`](/guides/basic-features/data/data-fetch#route-loader) API 获取到请求头来实现。
326
-
327
- 需要注意的是,此时获取到的是 HTML 请求的请求头,不一定适用于接口请求,因此**千万不能**透传所有请求头。并且,一些后端接口,或是通用网关,会根据请求头中的信息做校验,全量透传容易出现各种难以排查的问题,推荐**按需透传**。
328
-
329
- 如果实在需要透传所有请求头,请务必过滤 `host` 字段。