@modern-js/main-doc 3.0.1 → 3.0.2
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/docs/en/_nav.json +1 -1
- package/docs/en/apis/app/commands.mdx +1 -1
- package/docs/en/community/blog/_meta.json +7 -1
- package/docs/en/community/blog/v3-release-note.mdx +625 -0
- package/docs/en/components/rsbuild.mdx +1 -1
- package/docs/en/configure/app/builder-plugins.mdx +1 -1
- package/docs/en/configure/app/dev/server.mdx +6 -6
- package/docs/en/configure/app/resolve/alias-strategy.mdx +1 -1
- package/docs/en/configure/app/resolve/dedupe.mdx +1 -1
- package/docs/en/configure/app/security/sri.mdx +1 -1
- package/docs/en/configure/app/server/rsc.mdx +2 -2
- package/docs/en/configure/app/source/decorators.mdx +1 -1
- package/docs/en/configure/app/tools/bundler-chain.mdx +1 -1
- package/docs/en/configure/app/tools/swc.mdx +2 -2
- package/docs/en/guides/advanced-features/compatibility.mdx +1 -1
- package/docs/en/guides/advanced-features/page-performance/optimize-bundle.mdx +1 -1
- package/docs/en/guides/basic-features/css/css.mdx +4 -4
- package/docs/en/guides/basic-features/css/tailwindcss.mdx +2 -2
- package/docs/en/guides/basic-features/render/rsc.mdx +137 -8
- package/docs/en/guides/concept/builder.mdx +3 -3
- package/docs/en/guides/get-started/tech-stack.mdx +3 -3
- package/docs/en/guides/topic-detail/module-federation/application.mdx +6 -6
- package/docs/en/guides/topic-detail/module-federation/deploy.mdx +2 -2
- package/docs/en/guides/topic-detail/module-federation/i18n.mdx +12 -12
- package/docs/en/guides/topic-detail/module-federation/introduce.mdx +1 -1
- package/docs/en/guides/topic-detail/module-federation/ssr.mdx +4 -4
- package/docs/en/guides/topic-detail/module-federation/usage.mdx +7 -7
- package/docs/en/guides/troubleshooting/builder.mdx +4 -4
- package/docs/en/guides/upgrade/config.mdx +31 -3
- package/docs/en/plugin/cli-plugins/api.mdx +9 -9
- package/docs/en/plugin/introduction.mdx +5 -5
- package/docs/zh/_nav.json +1 -1
- package/docs/zh/apis/app/commands.mdx +1 -1
- package/docs/zh/community/blog/_meta.json +7 -1
- package/docs/zh/community/blog/v3-release-note.mdx +626 -0
- package/docs/zh/components/rsbuild.mdx +1 -1
- package/docs/zh/configure/app/builder-plugins.mdx +1 -1
- package/docs/zh/configure/app/dev/server.mdx +6 -6
- package/docs/zh/configure/app/resolve/alias-strategy.mdx +1 -1
- package/docs/zh/configure/app/resolve/dedupe.mdx +1 -1
- package/docs/zh/configure/app/security/sri.mdx +1 -1
- package/docs/zh/configure/app/server/rsc.mdx +2 -2
- package/docs/zh/configure/app/source/decorators.mdx +1 -1
- package/docs/zh/configure/app/tools/bundler-chain.mdx +1 -1
- package/docs/zh/configure/app/tools/swc.mdx +2 -2
- package/docs/zh/guides/advanced-features/compatibility.mdx +1 -1
- package/docs/zh/guides/advanced-features/page-performance/optimize-bundle.mdx +1 -1
- package/docs/zh/guides/basic-features/css/css.mdx +4 -4
- package/docs/zh/guides/basic-features/css/tailwindcss.mdx +2 -2
- package/docs/zh/guides/basic-features/render/rsc.mdx +222 -8
- package/docs/zh/guides/concept/builder.mdx +3 -3
- package/docs/zh/guides/get-started/tech-stack.mdx +3 -3
- package/docs/zh/guides/topic-detail/module-federation/application.mdx +6 -6
- package/docs/zh/guides/topic-detail/module-federation/deploy.mdx +2 -2
- package/docs/zh/guides/topic-detail/module-federation/i18n.mdx +12 -12
- package/docs/zh/guides/topic-detail/module-federation/introduce.mdx +1 -1
- package/docs/zh/guides/topic-detail/module-federation/ssr.mdx +4 -4
- package/docs/zh/guides/topic-detail/module-federation/usage.mdx +7 -7
- package/docs/zh/guides/troubleshooting/builder.mdx +4 -4
- package/docs/zh/guides/upgrade/config.mdx +31 -3
- package/docs/zh/plugin/cli-plugins/api.mdx +9 -9
- package/docs/zh/plugin/introduction.mdx +5 -5
- package/package.json +2 -2
- package/src/components/RsbuildLink/index.tsx +1 -1
- package/src/pages/index.tsx +1 -1
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Modern.js v3 发布
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Modern.js v3 发布:全面拥抱 Rspack
|
|
6
|
+
|
|
7
|
+
> 发表于 2025.02.06
|
|
8
|
+
|
|
9
|
+
## 前言
|
|
10
|
+
|
|
11
|
+
[Modern.js 2.0 发布](./v2-release-note.mdx) 至今,已过去三年时间,感谢社区开发者们对 Modern.js 的使用和信任。Modern.js 一直保持稳定的迭代,累计发布了超过 100 个版本。
|
|
12
|
+
|
|
13
|
+
在这三年中,我们不断扩充新特性,持续进行代码重构与优化,也收到了非常多的社区反馈,这些经验成为了 3.0 版本改进的重要参考。经过慎重考虑,我们决定发布 Modern.js 3.0,对框架进行一次全面的升级。
|
|
14
|
+
|
|
15
|
+
## Modern.js 2.0 到 3.0 的演变
|
|
16
|
+
|
|
17
|
+
从 Modern.js 2.0 到 3.0,有两个核心转变:
|
|
18
|
+
|
|
19
|
+
**更聚焦,专注于 Web 框架**
|
|
20
|
+
|
|
21
|
+
- Modern.js 2.0:包含 Modern.js App、Modern.js Module、Modern.js Doc
|
|
22
|
+
- Modern.js 3.0:只代表 Modern.js App,Modern.js Module 和 Modern.js Doc 已孵化为 [Rslib](https://rslib.rs) 与 [Rspress](https://rspress.dev)
|
|
23
|
+
|
|
24
|
+
**更开放,积极面向社区工具**
|
|
25
|
+
|
|
26
|
+
- Modern.js 2.0:内置各类工具、框架独特的 API 设计
|
|
27
|
+
- Modern.js 3.0:强化插件体系,完善接入能力,推荐社区优质方案
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Modern.js 3.0 新特性
|
|
32
|
+
|
|
33
|
+
### React Server Component
|
|
34
|
+
|
|
35
|
+
:::tip TL;DR
|
|
36
|
+
Modern.js 3.0 集成 React Server Component,支持 CSR 和 SSR 项目,并支持渐进式迁移。
|
|
37
|
+
:::
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
#### 什么是 React Server Component
|
|
42
|
+
|
|
43
|
+
React Server Components(服务端组件)是一种新的组件类型,它允许**组件逻辑完全在服务端执行**,并直接将渲染后的 UI 流式传输到客户端。与传统的客户端组件相比,服务端组件带来了以下特性:
|
|
44
|
+
|
|
45
|
+
| 特性 | 说明 |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| 零客户端包体积 | 组件代码不包含在客户端 JS Bundle 中,仅在服务端执行,加快首屏加载与渲染速度 |
|
|
48
|
+
| 更高的内聚性 | 组件可直接连接数据库、调用内部 API、读取本地文件,提高开发效率 |
|
|
49
|
+
| 渐进增强 | 可与客户端组件无缝混合使用,按需下放交互逻辑到客户端,在保持高性能的同时,支持复杂交互体验 |
|
|
50
|
+
|
|
51
|
+
需要明确的是,RSC 和 SSR 是**截然不同的概念**:
|
|
52
|
+
|
|
53
|
+
- **RSC**:描述的是**组件类型**,即组件在哪里执行(服务端 vs 客户端)
|
|
54
|
+
- **SSR**:描述的是**渲染模式**,即 HTML 在哪里生成(服务端 vs 客户端)
|
|
55
|
+
|
|
56
|
+
两者可以组合使用:Server Component 可以在 SSR 项目下使用,也可以在 CSR 项目下使用。在 Modern.js 3.0 中,我们同时支持这两种模式,开发者可以根据需求选择。
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
#### 开箱即用
|
|
61
|
+
|
|
62
|
+
在 Modern.js 3.0 中,只需在配置中启用 RSC 能力:
|
|
63
|
+
|
|
64
|
+
```ts title="modern.config.ts"
|
|
65
|
+
export default defineConfig({
|
|
66
|
+
server: {
|
|
67
|
+
rsc: true,
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
:::info
|
|
73
|
+
配置启用后,所有的路由组件都会默认成为 Server Component。项目中可能存在无法在服务端运行的组件,你可以先为这些组件添加 `'use client'` 标记,以保持原有行为,再逐步迁移。
|
|
74
|
+
:::
|
|
75
|
+
|
|
76
|
+
<video src="https://lf3-static.bytednsdoc.com/obj/eden-cn/nuvjhpqnuvr/rsc.mp4" controls autoplay loop muted style={{ width: '100%', borderRadius: 8 }} />
|
|
77
|
+
|
|
78
|
+
#### Modern.js 3.0 的 RSC 特性
|
|
79
|
+
|
|
80
|
+
Modern.js 一直选择 React Router 作为路由解决方案。去年,React Router v7 [宣布支持](https://remix.run/blog/rsc-preview) React Server Component,这为 Modern.js 提供了在 SPA 应用下实现 RSC 的基础。
|
|
81
|
+
|
|
82
|
+
相比于社区其他框架,Modern.js 对 RSC 做了几点优化:
|
|
83
|
+
|
|
84
|
+
- 使用 Rspack 最新的 RSC 插件构建,显著提升 RSC 项目构建速度;并进一步优化了产物体积。
|
|
85
|
+
- 不同于社区主流框架只支持 RSC + SSR,Modern.js 3.0 的 RSC 同样支持 CSR 项目
|
|
86
|
+
- 在路由跳转时,框架会自动将多个 Data Loader 和 Server Component 的请求合并为单个请求,并流式返回,提升页面性能
|
|
87
|
+
- 在嵌套路由场景下,路由组件类型不受父路由组件类型的影响,开发者可以从任意路由层级开始采用 Server Component
|
|
88
|
+
|
|
89
|
+
#### 渐进式迁移
|
|
90
|
+
|
|
91
|
+
基于灵活的组件边界控制能力,Modern.js 3.0 提供了渐进式的迁移方式。Modern.js 3.0 允许基于**路由组件维度**的 Server Component 迁移,无需迁移整条组件树链路。
|
|
92
|
+
|
|
93
|
+

|
|
94
|
+
|
|
95
|
+
:::info
|
|
96
|
+
更多 React Server Component 的详细内容,可以参考:[React Server Component](/guides/basic-features/render/rsc)
|
|
97
|
+
:::
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### 拥抱 Rspack
|
|
102
|
+
|
|
103
|
+
:::tip TL;DR
|
|
104
|
+
Modern.js 3.0 移除了对 webpack 的支持,全面拥抱 Rspack,并升级到最新的 Rspack & Rsbuild 2.0。
|
|
105
|
+
:::
|
|
106
|
+
|
|
107
|
+
在 2023 年,我们开源了 Rspack,并在 Modern.js 中支持将 Rspack 作为可选的打包工具。在字节内部,超过 60% 的 Modern.js 项目已经切换到 Rspack 构建。
|
|
108
|
+
|
|
109
|
+
经过两年多发展,Rspack 在社区中的月下载量已超过 1000 万次,成长为行业内被广泛使用的打包工具;同时,Modern.js 的 Rspack 构建模式也得到持续完善。
|
|
110
|
+
|
|
111
|
+

|
|
112
|
+
|
|
113
|
+
在 Modern.js 3.0 中,我们决定移除对 webpack 的支持,从而使 Modern.js 变得更加轻量和高效,并能更充分地利用 Rspack 的新特性。
|
|
114
|
+
|
|
115
|
+
#### 更顺畅的开发体验
|
|
116
|
+
|
|
117
|
+
Modern.js 3.0 在移除 webpack 后,能够更好地遵循 Rspack 最佳实践,在构建性能、安装速度等方面均有提升:
|
|
118
|
+
|
|
119
|
+
**底层依赖升级**
|
|
120
|
+
|
|
121
|
+
Modern.js 3.0 将底层依赖的 Rspack 和 Rsbuild 升级至 2.0 版本,并基于新版本优化了默认构建配置,使整体行为更加一致。
|
|
122
|
+
|
|
123
|
+
参考以下文档了解底层行为变化:
|
|
124
|
+
|
|
125
|
+
- [Rsbuild 2.0 升级指南](https://rsbuild.dev/zh/guide/upgrade/v1-to-v2)
|
|
126
|
+
- [Rspack 2.0 不兼容更新](https://github.com/web-infra-dev/rspack/discussions/9270)
|
|
127
|
+
|
|
128
|
+
**更快的构建速度**
|
|
129
|
+
|
|
130
|
+
Modern.js 通过 Rspack 的多项特性来减少构建耗时:
|
|
131
|
+
|
|
132
|
+
- 默认启用 Barrel 文件优化:构建组件库速度提升 20%
|
|
133
|
+
- 默认启用持久化缓存:非首次构建的速度提升 50%+
|
|
134
|
+
|
|
135
|
+
**更快的安装速度**
|
|
136
|
+
|
|
137
|
+
移除 webpack 相关依赖后,Modern.js 3.0 的构建依赖数量和体积均明显减少:
|
|
138
|
+
|
|
139
|
+
- npm 依赖数量减少 40%
|
|
140
|
+
- 安装体积减少 31 MB
|
|
141
|
+
|
|
142
|
+
#### 更小的构建产物
|
|
143
|
+
|
|
144
|
+
Modern.js 现在默认启用 Rspack 的多项产物优化策略,能够比 webpack 生成更小的产物体积,例如:
|
|
145
|
+
|
|
146
|
+
**增强 Tree shaking**
|
|
147
|
+
|
|
148
|
+
增强了 tree shaking 分析能力,可以处理更多动态导入语法,例如解构赋值:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
// 参数中的解构访问
|
|
152
|
+
import('./module').then(({ value }) => {
|
|
153
|
+
console.log(value);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// 函数体内的解构访问
|
|
157
|
+
import('./module').then((mod) => {
|
|
158
|
+
const { value } = mod;
|
|
159
|
+
console.log(value);
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**常量内联**
|
|
164
|
+
|
|
165
|
+
对常量进行跨模块内联,有助于压缩工具进行更准确的静态分析,从而消除无用的代码分支:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
// constants.js
|
|
169
|
+
export const ENABLED = true;
|
|
170
|
+
|
|
171
|
+
// index.js
|
|
172
|
+
import { ENABLED } from './constants';
|
|
173
|
+
if (ENABLED) {
|
|
174
|
+
doSomething();
|
|
175
|
+
} else {
|
|
176
|
+
doSomethingElse();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 构建产物 - 无用分支被消除
|
|
180
|
+
doSomething();
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### 全链路可扩展
|
|
186
|
+
|
|
187
|
+
:::tip TL;DR
|
|
188
|
+
Modern.js 3.0 正式开放完整插件体系,提供运行时、服务端插件,同时支持灵活处理应用入口。
|
|
189
|
+
:::
|
|
190
|
+
|
|
191
|
+
Modern.js 2.0 提供了 CLI 插件与内测版本的运行时插件,允许开发者对项目进行扩展。但在实践过程中,我们发现现有的能力不足以支撑复杂的业务场景。
|
|
192
|
+
|
|
193
|
+
Modern.js 3.0 提供了更灵活的定制能力,允许为应用编写全流程的插件,帮助团队统一业务逻辑、减少重复代码:
|
|
194
|
+
|
|
195
|
+
- **CLI 插件**:在构建阶段扩展功能,如添加命令、修改配置
|
|
196
|
+
- **Runtime 插件**:在渲染阶段扩展功能,如数据预取、组件封装
|
|
197
|
+
- **Server 插件**:在服务端扩展功能,如添加中间件、修改请求响应
|
|
198
|
+
|
|
199
|
+
#### 运行时插件
|
|
200
|
+
|
|
201
|
+
运行时插件在 CSR 与 SSR 过程中都会运行,新版本提供了两个核心钩子:
|
|
202
|
+
|
|
203
|
+
- `onBeforeRender`:在渲染前执行逻辑,可用于数据预取、注入全局数据
|
|
204
|
+
- `wrapRoot`:封装根组件,添加全局 Provider、布局组件等
|
|
205
|
+
|
|
206
|
+
你可以在 `src/modern.runtime.ts` 中注册插件,相比在入口手动引入高阶组件,运行时插件可插拔、易更新,在多入口场景下无需重复引入:
|
|
207
|
+
|
|
208
|
+
```ts title="src/modern.runtime.tsx"
|
|
209
|
+
import { defineRuntimeConfig } from "@modern-js/runtime";
|
|
210
|
+
|
|
211
|
+
export default defineRuntimeConfig({
|
|
212
|
+
plugins: [
|
|
213
|
+
{
|
|
214
|
+
name: "my-runtime-plugin",
|
|
215
|
+
setup: (api) => {
|
|
216
|
+
api.onBeforeRender((context) => {
|
|
217
|
+
context.globalData = { theme: "dark" };
|
|
218
|
+
});
|
|
219
|
+
api.wrapRoot((App) => (props) => <App {...props} />);
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
:::info
|
|
227
|
+
更多 Runtime 插件使用方式,请查看文档:[Runtime 插件](/plugin/runtime-plugins/api)
|
|
228
|
+
:::
|
|
229
|
+
|
|
230
|
+
#### 服务端中间件
|
|
231
|
+
|
|
232
|
+
在实践过程中我们发现,部分项目需要扩展 Web Server,例如鉴权、数据预取、降级处理、动态 HTML 脚本注入等。
|
|
233
|
+
|
|
234
|
+
在 Modern.js 3.0 中,我们使用 [Hono](https://hono.dev) 重构了 Web Server,并正式开放了服务端中间件与插件的能力。开发者可以使用 Hono 的中间件来完成需求:
|
|
235
|
+
|
|
236
|
+
```ts title="server/modern.server.ts"
|
|
237
|
+
import { defineServerConfig, type MiddlewareHandler } from "@modern-js/server-runtime";
|
|
238
|
+
|
|
239
|
+
const timingMiddleware: MiddlewareHandler = async (c, next) => {
|
|
240
|
+
const start = Date.now();
|
|
241
|
+
await next();
|
|
242
|
+
const duration = Date.now() - start;
|
|
243
|
+
c.header('X-Response-Time', `${duration}ms`);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const htmlMiddleware: MiddlewareHandler = async (c, next) => {
|
|
247
|
+
await next();
|
|
248
|
+
const html = await c.res.text();
|
|
249
|
+
const modified = html.replace(
|
|
250
|
+
"<head>",
|
|
251
|
+
'<head><meta name="generator" content="Modern.js">'
|
|
252
|
+
);
|
|
253
|
+
c.res = c.body(modified, { status: c.res.status, headers: c.res.headers });
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
export default defineServerConfig({
|
|
257
|
+
middlewares: [timingMiddleware],
|
|
258
|
+
renderMiddlewares: [htmlMiddleware],
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
:::info
|
|
263
|
+
更多服务端插件使用方式,可以查看文档:[自定义 Web Server](/guides/advanced-features/web-server)
|
|
264
|
+
:::
|
|
265
|
+
|
|
266
|
+
#### 自定义入口
|
|
267
|
+
|
|
268
|
+
在 Modern.js 3.0 中,我们重构了自定义入口,相比于旧版 API 更加清晰灵活:
|
|
269
|
+
|
|
270
|
+
```ts title="src/entry.tsx"
|
|
271
|
+
import { createRoot } from '@modern-js/runtime/react';
|
|
272
|
+
import { render } from '@modern-js/runtime/browser';
|
|
273
|
+
|
|
274
|
+
const ModernRoot = createRoot();
|
|
275
|
+
|
|
276
|
+
async function beforeRender() {
|
|
277
|
+
// 渲染前的异步操作,如初始化 SDK、获取用户信息等
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
beforeRender().then(() => {
|
|
281
|
+
render(<ModernRoot />);
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
:::info
|
|
286
|
+
更多入口使用方式,请查看文档:[入口](/guides/concept/entries)
|
|
287
|
+
:::
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 路由优化
|
|
292
|
+
|
|
293
|
+
:::tip TL;DR
|
|
294
|
+
Modern.js 3.0 内置 React Router v7,提供配置式路由能力与 AI 友好的调试方式。
|
|
295
|
+
:::
|
|
296
|
+
|
|
297
|
+
#### 内置 React Router v7
|
|
298
|
+
|
|
299
|
+
在 Modern.js 3.0 中,我们统一升级到 React Router v7,并废弃了对 v5 和 v6 的内置支持。这一决策基于以下考虑:
|
|
300
|
+
|
|
301
|
+
**版本演进与稳定性**
|
|
302
|
+
|
|
303
|
+
React Router v6 是一个重要的过渡版本,它引入了许多新特性(如数据加载、错误边界等)。而 v7 在保持 v6 API 兼容性的基础上,进一步优化了性能、稳定性和开发体验。随着 React Router 团队将 Remix 定位为独立框架,React Router 核心库可能会在 v7 版本上长期维护,使其成为更可靠的选择。
|
|
304
|
+
|
|
305
|
+
**升级路径**
|
|
306
|
+
|
|
307
|
+
- **从 v6 升级**:React Router v7 对 v6 开发者来说是无破坏性变更的升级。在 Modern.js 2.0 中,我们已提供了 React Router v7 插件支持,你可以通过插件方式渐进式升级,验证兼容性后再迁移到 Modern.js 3.0。
|
|
308
|
+
- **从 v5 升级**:v5 到 v7 存在较大的 API 变化,建议参考 [React Router 官方迁移指南](https://reactrouter.com/upgrading/v5) 进行迁移。
|
|
309
|
+
|
|
310
|
+
#### 配置式路由
|
|
311
|
+
|
|
312
|
+
在 Modern.js 中,我们推荐使用约定式路由来组织代码。但在实际业务中,开发者偶尔遇到以下场景:
|
|
313
|
+
|
|
314
|
+
- 多路径指向同一组件
|
|
315
|
+
- 灵活的路由控制
|
|
316
|
+
- 条件性路由
|
|
317
|
+
- 遗留项目迁移
|
|
318
|
+
|
|
319
|
+
因此,Modern.js 3.0 提供了完整的配置式路由支持,可以与约定式路由一起使用,或两者分别单独使用。
|
|
320
|
+
|
|
321
|
+
```ts title="src/modern.routes.ts"
|
|
322
|
+
import { defineRoutes } from "@modern-js/runtime/config-routes";
|
|
323
|
+
|
|
324
|
+
export default defineRoutes(({ route, layout, page }) => {
|
|
325
|
+
return [
|
|
326
|
+
route("home.tsx", "/"),
|
|
327
|
+
route("about.tsx", "about"),
|
|
328
|
+
route("blog.tsx", "blog/:id"),
|
|
329
|
+
];
|
|
330
|
+
});
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
:::info
|
|
334
|
+
更多配置式路由使用方式,请查看文档:[配置式路由](/guides/basic-features/routes/config-routes)
|
|
335
|
+
:::
|
|
336
|
+
|
|
337
|
+
#### 路由调试
|
|
338
|
+
|
|
339
|
+
运行 `npx modern routes` 命令即可在 `dist/routes-inspect.json` 文件中生成完整的路由结构分析报告。
|
|
340
|
+
|
|
341
|
+
报告中会显示每个路由的路径、组件文件、数据加载器、错误边界、Loading 组件等完整信息,帮助开发者快速了解项目的路由配置,快速定位和排查路由相关问题。结构化的 JSON 格式也便于 AI agent 理解和分析路由结构,提升 AI 辅助开发的效率。
|
|
342
|
+
|
|
343
|
+
:::info
|
|
344
|
+
具体使用方式,请查看文档:[路由调试](/guides/basic-features/routes/config-routes#调试路由)
|
|
345
|
+
:::
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
### 服务端渲染
|
|
350
|
+
|
|
351
|
+
:::tip TL;DR
|
|
352
|
+
Modern.js 3.0 重做了 SSG 能力,提供了灵活的缓存能力,对降级策略也进行了进一步的完善。
|
|
353
|
+
:::
|
|
354
|
+
|
|
355
|
+
#### 静态站点生成(SSG)
|
|
356
|
+
|
|
357
|
+
在 Modern.js 2.0 中,我们提供了静态站点生成的能力。这个能力非常适合用在可以静态渲染的页面中,能极大的提升页面首屏性能。
|
|
358
|
+
|
|
359
|
+
在新版本中,我们对 SSG 进行了重新设计:
|
|
360
|
+
|
|
361
|
+
- 数据获取使用 Data Loader,与非 SSG 场景保持一致
|
|
362
|
+
- 简化了 API,降低理解成本
|
|
363
|
+
- 与约定式路由更好地结合
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
在新版本中,你可以通过 data loader 进行数据获取,与非 SSG 场景保持一致。然后在 ssg.routes 配置中即可直接指定要渲染的路由:
|
|
367
|
+
|
|
368
|
+
```ts title="modern.config.ts"
|
|
369
|
+
export default defineConfig({
|
|
370
|
+
output: {
|
|
371
|
+
ssg: {
|
|
372
|
+
routes: ['/blog'],
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
```ts title="routes/blog/page.data.ts"
|
|
379
|
+
export const loader = async () => {
|
|
380
|
+
const articles = await fetchArticles();
|
|
381
|
+
return { articles };
|
|
382
|
+
};
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
:::info
|
|
386
|
+
更多 SSG 的使用方式,请查看文档:[SSG](/guides/basic-features/render/ssg)
|
|
387
|
+
:::
|
|
388
|
+
|
|
389
|
+
#### 缓存机制
|
|
390
|
+
|
|
391
|
+
Modern.js 3.0 中提供了不同维度的缓存机制,帮助项目提升首屏性能。所有缓存均支持灵活配置,比如可以支持类似 HTTP 的 `stale-while-revalidate` 策略:
|
|
392
|
+
|
|
393
|
+
**渲染缓存**
|
|
394
|
+
|
|
395
|
+
支持将 SSR 结果进行整页的缓存,在 `server/cache.ts` 中配置:
|
|
396
|
+
|
|
397
|
+
```ts title="server/cache.ts"
|
|
398
|
+
import type { CacheOption } from '@modern-js/server-runtime';
|
|
399
|
+
|
|
400
|
+
export const cacheOption: CacheOption = {
|
|
401
|
+
maxAge: 500, // ms
|
|
402
|
+
staleWhileRevalidate: 1000, // ms
|
|
403
|
+
};
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
:::info
|
|
407
|
+
使用渲染缓存,请查看文档:[渲染缓存](/guides/basic-features/render/ssr-cache)
|
|
408
|
+
:::
|
|
409
|
+
|
|
410
|
+
**数据缓存**
|
|
411
|
+
|
|
412
|
+
我们在新版本中提供了 `cache` 函数,相比渲染缓存它提供了更精细的数据粒度控制。当多个数据请求依赖同一份数据时,`cache` 可以避免重复请求:
|
|
413
|
+
|
|
414
|
+
```ts title="server/loader.ts"
|
|
415
|
+
import { cache } from "@modern-js/runtime/cache";
|
|
416
|
+
import { fetchUserData, fetchUserProjects, fetchUserTeam } from "./api";
|
|
417
|
+
|
|
418
|
+
// 缓存用户数据,避免重复请求
|
|
419
|
+
const getUser = cache(fetchUserData);
|
|
420
|
+
|
|
421
|
+
const getProjects = async () => {
|
|
422
|
+
const user = await getUser("test-user");
|
|
423
|
+
return fetchUserProjects(user.id);
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
const getTeam = async () => {
|
|
427
|
+
const user = await getUser("test-user"); // 复用缓存,不会重复请求
|
|
428
|
+
return fetchUserTeam(user.id);
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
export const loader = async () => {
|
|
432
|
+
// getProjects 和 getTeam 都依赖 getUser,但 getUser 只会执行一次
|
|
433
|
+
const [projects, team] = await Promise.all([getProjects(), getTeam()]);
|
|
434
|
+
return { projects, team };
|
|
435
|
+
};
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
:::info
|
|
439
|
+
更多数据缓存的使用方式,请查看文档:[数据缓存](/guides/basic-features/data/data-cache)
|
|
440
|
+
:::
|
|
441
|
+
|
|
442
|
+
#### 灵活的降级策略
|
|
443
|
+
|
|
444
|
+
在实践过程中,我们沉淀了多维度的降级策略:
|
|
445
|
+
|
|
446
|
+
| 类型 | 触发方式 | 降级行为 | 使用场景 |
|
|
447
|
+
| --- | --- | --- | --- |
|
|
448
|
+
| 异常降级 | Data Loader 执行报错 | 触发 ErrorBoundary | 数据请求异常兜底 |
|
|
449
|
+
| 组件渲染报错 | 服务端渲染异常 | 降级到 CSR,复用已有数据渲染 | 服务端渲染异常兜底 |
|
|
450
|
+
| 业务降级 | Loader 抛出 `throw Response` | 触发 ErrorBoundary,返回对应 HTTP 状态码 | 404、权限校验等业务场景 |
|
|
451
|
+
| 配置 Client Loader | 配置 Client Loader | 绕过 SSR,直接请求数据源 | 需要在客户端直接获取数据的场景 |
|
|
452
|
+
| 强制降级 | Query 参数 `?__csr=true` | 跳过 SSR,返回 CSR 页面 | 调试、临时降级 |
|
|
453
|
+
| 强制降级 | 请求头 `x-modern-ssr-fallback` | 跳过 SSR,返回 CSR 页面 | 网关层控制降级 |
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
### 轻量 BFF
|
|
458
|
+
|
|
459
|
+
:::tip TL;DR
|
|
460
|
+
Modern.js 3.0 基于 Hono 重构了 Web Server,提供基于 Hono 的一体化函数,同时支持跨项目调用。
|
|
461
|
+
:::
|
|
462
|
+
|
|
463
|
+
#### Hono 一体化函数
|
|
464
|
+
|
|
465
|
+
在 Modern.js 3.0 中,我们使用 [Hono](https://hono.dev) 作为 BFF 的运行时框架,开发者可以基于 Hono 生态扩展 BFF Server,享受 Hono 轻量、高性能的优势。
|
|
466
|
+
|
|
467
|
+
通过 `useHonoContext` 可以获取完整的 Hono 上下文,访问请求信息、设置响应头等:
|
|
468
|
+
|
|
469
|
+
```ts title="api/lambda/user.ts"
|
|
470
|
+
import { useHonoContext } from '@modern-js/server-runtime';
|
|
471
|
+
|
|
472
|
+
export const get = async () => {
|
|
473
|
+
const c = useHonoContext();
|
|
474
|
+
const token = c.req.header('Authorization');
|
|
475
|
+
c.header('X-Custom-Header', 'modern-js');
|
|
476
|
+
const id = c.req.query('id');
|
|
477
|
+
|
|
478
|
+
return { userId: id, authenticated: !!token };
|
|
479
|
+
};
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
#### 跨项目调用
|
|
483
|
+
|
|
484
|
+
在过去,Modern.js BFF 只能在当前项目中使用,而我们陆续收到开发者反馈,希望能够在不同项目中使用。这多数情况是由于开发者的迁移成本、运维成本造成的,相比于抽出原有代码再部署一个,显然复用已有服务更加合理。
|
|
485
|
+
|
|
486
|
+
为了保证开发者能得到与当前项目一体化调用类似的体验,我们提供了跨项目调用的能力。
|
|
487
|
+
|
|
488
|
+
:::info
|
|
489
|
+
更多 BFF 的使用方式,请查看文档:[BFF](/guides/advanced-features/bff)
|
|
490
|
+
:::
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
### Module Federation 深度集成
|
|
495
|
+
|
|
496
|
+
:::tip TL;DR
|
|
497
|
+
Modern.js 3.0 与 [Module Federation 2.0](https://module-federation.io) 深度集成,支持 MF SSR 和应用级别模块导出。
|
|
498
|
+
:::
|
|
499
|
+
|
|
500
|
+
#### MF SSR
|
|
501
|
+
|
|
502
|
+
Modern.js 3.0 支持在 SSR 应用中使用 Module Federation,组合使用模块联邦和服务端渲染能力,为用户提供更好的首屏性能体验。
|
|
503
|
+
|
|
504
|
+
```ts title="modern.config.ts"
|
|
505
|
+
export default defineConfig({
|
|
506
|
+
server: {
|
|
507
|
+
ssr: {
|
|
508
|
+
mode: 'stream',
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
配合 Module Federation 的[数据获取](https://module-federation.io/zh/guide/basic/data-fetch/index.html)能力,每个远程模块都可以定义自己的数据获取逻辑:
|
|
515
|
+
|
|
516
|
+
```ts title="src/components/Button.data.ts"
|
|
517
|
+
export const fetchData = async () => {
|
|
518
|
+
return {
|
|
519
|
+
data: `Server time: ${new Date().toISOString()}`,
|
|
520
|
+
};
|
|
521
|
+
};
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
```tsx title="src/components/Button.tsx"
|
|
525
|
+
export const Button = (props: { mfData: { data: string } }) => {
|
|
526
|
+
return <button>{props.mfData?.data}</button>;
|
|
527
|
+
};
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
#### 应用级别模块
|
|
531
|
+
|
|
532
|
+
不同于传统的组件级别共享,Modern.js 3.0 支持导出**应用级别模块**——具备完整路由能力、可以像独立应用一样运行的模块。这是微前端场景中的重要能力。
|
|
533
|
+
|
|
534
|
+
**生产者导出应用**
|
|
535
|
+
|
|
536
|
+
```ts title="src/export-App.tsx"
|
|
537
|
+
import '@modern-js/runtime/registry/index';
|
|
538
|
+
import { render } from '@modern-js/runtime/browser';
|
|
539
|
+
import { createRoot } from '@modern-js/runtime/react';
|
|
540
|
+
import { createBridgeComponent } from '@module-federation/modern-js/react';
|
|
541
|
+
|
|
542
|
+
const ModernRoot = createRoot();
|
|
543
|
+
export const provider = createBridgeComponent({
|
|
544
|
+
rootComponent: ModernRoot,
|
|
545
|
+
render: (Component, dom) => render(Component, dom),
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
export default provider;
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
**消费者加载应用**
|
|
552
|
+
|
|
553
|
+
```tsx title="src/routes/remote/$.tsx"
|
|
554
|
+
import { createRemoteAppComponent } from '@module-federation/modern-js/react';
|
|
555
|
+
import { loadRemote } from '@module-federation/modern-js/runtime';
|
|
556
|
+
|
|
557
|
+
const RemoteApp = createRemoteAppComponent({
|
|
558
|
+
loader: () => loadRemote('remote/app'),
|
|
559
|
+
fallback: ({ error }) => <div>Error: {error.message}</div>,
|
|
560
|
+
loading: <div>Loading...</div>,
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
export default RemoteApp;
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
通过通配路由 `$.tsx`,所有访问 `/remote/*` 的请求都会进入远程应用,远程应用内部的路由也能正常工作。
|
|
567
|
+
|
|
568
|
+
:::info
|
|
569
|
+
更多 Module Federation 的使用方式,请查看文档:[Module Federation](/guides/topic-detail/module-federation/introduce)
|
|
570
|
+
:::
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
### 技术栈更新
|
|
575
|
+
|
|
576
|
+
:::tip TL;DR
|
|
577
|
+
Modern.js 3.0 升级 React 19,最低支持 Node.js 20。
|
|
578
|
+
:::
|
|
579
|
+
|
|
580
|
+
#### React 19
|
|
581
|
+
|
|
582
|
+
Modern.js 3.0 新项目默认使用 React 19,最低支持 React 18。
|
|
583
|
+
|
|
584
|
+
如果你的项目仍在使用 React 16 或 React 17,请先参考 [React 19 官方升级指南](https://react.dev/blog/2024/04/25/react-19-upgrade-guide) 完成版本升级。
|
|
585
|
+
|
|
586
|
+
#### Node.js 20
|
|
587
|
+
|
|
588
|
+
随着 Node.js 不断推进版本演进,Node.js 18 已经 EOL。在 Modern.js 3.0 中,推荐使用 Node.js 22 LTS,不再保证对 Node.js 18 的支持。
|
|
589
|
+
|
|
590
|
+
#### Storybook Rsbuild
|
|
591
|
+
|
|
592
|
+
在 Modern.js 3.0 中,我们基于 [Storybook Rsbuild](https://github.com/rspack-contrib/storybook-rsbuild) 实现了使用 Storybook 构建 Modern.js 应用。
|
|
593
|
+
|
|
594
|
+
通过 Storybook Addon,我们将 Modern.js 配置转换合并为 Rsbuild 配置,并通过 Storybook Rsbuild 驱动构建,让 Storybook 调试与开发命令保持配置对齐。
|
|
595
|
+
|
|
596
|
+
:::info
|
|
597
|
+
更多 Storybook 使用方式,请查看文档:[使用 Storybook](/guides/basic-features/debug/using-storybook)
|
|
598
|
+
:::
|
|
599
|
+
|
|
600
|
+
#### 使用 Biome
|
|
601
|
+
|
|
602
|
+
随着社区技术不断发展,更快、更简洁的工具链已经成熟。在 Modern.js 3.0 中,新项目默认使用 [Biome](https://biomejs.dev/) 作为代码检查和格式化工具。
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
## 从 Modern.js 2.0 升级到 3.0
|
|
607
|
+
|
|
608
|
+
### 主要变更
|
|
609
|
+
|
|
610
|
+
升级 Modern.js 3.0 意味着拥抱更轻量、更标准的现代化开发范式。通过全面对齐 Rspack 与 React 19 等主流生态,彻底解决历史包袱带来的维护痛点,显著提升构建与运行性能。
|
|
611
|
+
|
|
612
|
+
未来,我们也会基于 Modern.js 3.0 提供更多的 AI 集成与最佳实践,配合灵活的全栈插件系统,让开发者能以极低的学习成本复用社区经验,实现开发效率的质变与应用架构的现代化升级。
|
|
613
|
+
|
|
614
|
+
:::info
|
|
615
|
+
更多改进与变更,请查看文档:[升级指南](/guides/upgrade/overview)
|
|
616
|
+
:::
|
|
617
|
+
|
|
618
|
+
## 反馈和社区
|
|
619
|
+
|
|
620
|
+
最后,再次感谢每一位给予我们反馈和支持的开发者,我们将继续与大家保持沟通,在相互支持中共同成长。
|
|
621
|
+
|
|
622
|
+
如果你在使用过程中遇到问题,欢迎通过以下方式反馈:
|
|
623
|
+
|
|
624
|
+
- [GitHub Issues](https://github.com/web-infra-dev/modern.js/issues)
|
|
625
|
+
- [Discord](https://discord.gg/qPCqYg38De)
|
|
626
|
+
- [Lark](https://applink.larkoffice.com/client/chat/chatter/add_by_link?link_token=d21hc667-9403-48a9-ba32-bc1440a80279)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
[Rsbuild](https://rsbuild.
|
|
1
|
+
[Rsbuild](https://v2.rsbuild.dev/) 是一个基于 Rspack 的 web 构建工具,它的目标是为 Rspack 用户提供开箱即用的构建能力,使开发者能够在零配置的情况下启动一个 web 项目。
|
|
2
2
|
|
|
3
3
|
Rsbuild 集成了社区中基于 Rust 的高性能工具,包括 Rspack 和 SWC,以提供一流的构建速度和开发体验。
|
|
@@ -11,7 +11,7 @@ sidebar_position: 21
|
|
|
11
11
|
|
|
12
12
|
Rsbuild 是 Modern.js 底层的构建工具,请阅读 [构建能力](/guides/concept/builder) 了解相关背景。
|
|
13
13
|
|
|
14
|
-
如果你想了解 Rsbuild 插件的编写方式,可以参考 [Rsbuild - 插件系统](https://rsbuild.
|
|
14
|
+
如果你想了解 Rsbuild 插件的编写方式,可以参考 [Rsbuild - 插件系统](https://v2.rsbuild.dev/zh/plugins/dev/index)。
|
|
15
15
|
|
|
16
16
|
## 注意事项
|
|
17
17
|
|
|
@@ -28,7 +28,7 @@ export default {
|
|
|
28
28
|
};
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
更多详细信息请参考 [Rsbuild - server.compress](https://rsbuild.
|
|
31
|
+
更多详细信息请参考 [Rsbuild - server.compress](https://v2.rsbuild.dev/zh/config/server/compress) 文档。
|
|
32
32
|
|
|
33
33
|
### headers
|
|
34
34
|
|
|
@@ -49,7 +49,7 @@ export default {
|
|
|
49
49
|
};
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
更多详细信息请参考 [Rsbuild - server.headers](https://rsbuild.
|
|
52
|
+
更多详细信息请参考 [Rsbuild - server.headers](https://v2.rsbuild.dev/zh/config/server/headers) 文档。
|
|
53
53
|
|
|
54
54
|
### historyApiFallback
|
|
55
55
|
|
|
@@ -68,7 +68,7 @@ export default {
|
|
|
68
68
|
};
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
更多配置选项请参考 [Rsbuild - server.historyApiFallback](https://rsbuild.
|
|
71
|
+
更多配置选项请参考 [Rsbuild - server.historyApiFallback](https://v2.rsbuild.dev/zh/config/server/history-api-fallback) 文档。
|
|
72
72
|
|
|
73
73
|
### watch
|
|
74
74
|
|
|
@@ -77,7 +77,7 @@ export default {
|
|
|
77
77
|
|
|
78
78
|
是否监听 `mock/`、`server/`、`api/` 等目录的文件变化。
|
|
79
79
|
|
|
80
|
-
更多详细信息请参考 [Rsbuild - dev.watchFiles](https://rsbuild.
|
|
80
|
+
更多详细信息请参考 [Rsbuild - dev.watchFiles](https://v2.rsbuild.dev/zh/config/dev/watch-files) 文档。
|
|
81
81
|
|
|
82
82
|
### cors
|
|
83
83
|
|
|
@@ -100,7 +100,7 @@ const defaultOptions = {
|
|
|
100
100
|
};
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
更多配置选项和详细用法请参考 [Rsbuild - server.cors](https://rsbuild.
|
|
103
|
+
更多配置选项和详细用法请参考 [Rsbuild - server.cors](https://v2.rsbuild.dev/zh/config/server/cors) 文档。
|
|
104
104
|
|
|
105
105
|
### proxy
|
|
106
106
|
|
|
@@ -124,5 +124,5 @@ export default {
|
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
:::tip
|
|
127
|
-
该选项与 Rsbuild 的 `server.proxy` 选项一致,更多用法请参考 [Rsbuild - server.proxy](https://v2.rsbuild.
|
|
127
|
+
该选项与 Rsbuild 的 `server.proxy` 选项一致,更多用法请参考 [Rsbuild - server.proxy](https://v2.rsbuild.dev/zh/config/server/proxy)。
|
|
128
128
|
:::
|