diff --git a/packages/document/docs/en/guides/basic-features/render/ssg.mdx b/packages/document/docs/en/guides/basic-features/render/ssg.mdx
index 0ee674528140..6267c9131071 100644
--- a/packages/document/docs/en/guides/basic-features/render/ssg.mdx
+++ b/packages/document/docs/en/guides/basic-features/render/ssg.mdx
@@ -27,11 +27,12 @@ export default defineConfig({
});
```
-::::info Scope
+:::info
- Use `output.ssg` for single-entry apps.
- Use `output.ssgByEntries` for multi-entry apps.
- If `output.ssg` is `true` and `output.ssgByEntries` is not set, all routes under all entries are treated as SSG routes.
-::::
+
+:::
## Development Debugging
@@ -92,36 +93,6 @@ Each route in **conventional routing** will generate a separate HTML file. Check
After running `pnpm run serve` to start the project, inspect the returned document in the Network tab of the browser's development tools. The document includes the fully rendered content from the component.
-### Preventing Default Behavior
-
-By default, all routes in **conventional routing** have SSG enabled. Modern.js provides another field to prevent the default SSG behavior.
-
-For example, in the following directory structure, routes `/`, `/user`, and `/user/profile` all have SSG enabled:
-
-```bash
-.
-├── src
-│ └── routes
-│ ├── layout.tsx
-│ ├── page.tsx
-│ └── user
-│ ├── layout.tsx
-│ ├── page.tsx
-│ └── profile
-│ └── page.tsx
-```
-
-You can disable the default behavior of certain routes by configuring `preventDefault`. After configuring as shown below, only the SSG pages for `/` and `/user/profile` will be generated:
-
-```js
-export default defineConfig({
- output: {
- ssg: {
- preventDefault: ['/user'],
- },
- },
-});
-```
## Using SSG in Manual Routing
diff --git a/packages/document/docs/en/guides/concept/entries.mdx b/packages/document/docs/en/guides/concept/entries.mdx
index 2be399c42750..396f51518b67 100644
--- a/packages/document/docs/en/guides/concept/entries.mdx
+++ b/packages/document/docs/en/guides/concept/entries.mdx
@@ -193,10 +193,15 @@ If you don't want to use any of Modern.js's runtime capabilities, you can also m
```js title=src/entry.tsx
import React from 'react';
-import ReactDOM from 'react-dom';
+import { createRoot } from 'react-dom/client';
import App from './App';
-ReactDOM.render(, document.getElementById('root'));
+const container = document.getElementById('root');
+
+if (container) {
+ const root = createRoot(container);
+ root.render();
+}
```
In this mode, **you will not be able to use Modern.js framework's runtime capabilities**, such as:
@@ -237,10 +242,6 @@ export default defineConfig({
});
```
-It is worth noting that, by default, Modern.js considers entries specified through the configuration as **framework mode entries** and will automatically generate the actual compilation entry.
-
-If your application is migrating from build tools like Webpack or Vite to the Modern.js framework, you typically need to enable the `disableMount` option in the entry configuration. In this case, Modern.js will treat the entry as a **build mode entry**.
-
## In-Depth
The concept of page entry is derived from the concept of [Entrypoint](https://webpack.js.org/concepts/entry-points/) in webpack. It is mainly used to configure JavaScript or other modules to be executed during application startup. webpack's [best practice](https://webpack.docschina.org/concepts/entry-points/#multi-page-application) for web applications usually corresponds entries to HTML output files, meaning each additional entry will eventually generate a corresponding HTML file in the output. The modules imported by the entry will be compiled and packaged into multiple Chunk outputs. For example, JavaScript modules may ultimately generate several file outputs similar to `dist/static/js/index.ea39u8.js`.
diff --git a/packages/document/docs/zh/guides/_meta.json b/packages/document/docs/zh/guides/_meta.json
index e978ec327731..4e99d86b2ae0 100644
--- a/packages/document/docs/zh/guides/_meta.json
+++ b/packages/document/docs/zh/guides/_meta.json
@@ -29,5 +29,10 @@
"name": "troubleshooting",
"label": "troubleshooting"
},
- "deprecated"
+ "deprecated",
+ {
+ "type": "dir",
+ "name": "upgrade",
+ "label": "从 Modern.js 2.0 升级"
+ }
]
diff --git a/packages/document/docs/zh/guides/basic-features/data/data-cache.mdx b/packages/document/docs/zh/guides/basic-features/data/data-cache.mdx
index 6cfa297a15c4..355bfa9ee0a9 100644
--- a/packages/document/docs/zh/guides/basic-features/data/data-cache.mdx
+++ b/packages/document/docs/zh/guides/basic-features/data/data-cache.mdx
@@ -67,7 +67,7 @@ interface CacheOptions {
## 使用范围
与 react 的 [cache](https://react.dev/reference/react/cache) 函数只能在 server component 组件中使用不同,
-EdenX 提供的 `cache` 函数可以在任意的前端或服务端的代码中使用。
+Modern.js 提供的 `cache` 函数可以在任意的前端或服务端的代码中使用。
## 详细用法
diff --git a/packages/document/docs/zh/guides/basic-features/render/ssg.mdx b/packages/document/docs/zh/guides/basic-features/render/ssg.mdx
index fb1fb0a5552f..9091f1fb5ec4 100644
--- a/packages/document/docs/zh/guides/basic-features/render/ssg.mdx
+++ b/packages/document/docs/zh/guides/basic-features/render/ssg.mdx
@@ -28,11 +28,12 @@ export default defineConfig({
});
```
-::::info 适用范围
+:::info 适用范围
- 单入口请使用 `output.ssg`。
- 多入口请使用 `output.ssgByEntries`。
- 当仅设置 `output.ssg: true` 且未配置 `output.ssgByEntries` 时,所有入口下的所有路由都会作为 SSG 路由处理。
-::::
+
+:::
## 开发环境调试
@@ -93,36 +94,6 @@ export default () => {
执行 `pnpm run serve` 启动项目后,访问页面,在浏览器我们工具的 Network 窗口,查看请求返回的文档,文档包含组件渲染后的完整页面内容。
-### 阻止默认行为
-
-默认情况下,**约定式路由**的路由会全部开启 SSG。Modern.js 提供了另一个字段,用来阻止默认的 SSG 行为。
-
-例如以下目录结构,`/`、`/user`、`/user/profle` 三条路由都开启 SSG:
-
-```bash
-.
-├── src
-│ └── routes
-│ ├── layout.tsx
-│ ├── page.tsx
-│ └── user
-│ ├── layout.tsx
-│ ├── page.tsx
-│ └── profile
-│ └── page.tsx
-```
-
-可以通过配置 `preventDefault` 来禁用某些路由的默认行为。进行下面配置后,最终只会生成 `/`、`/user/profle` 两条路由的 SSG 页面:
-
-```js
-export default defineConfig({
- output: {
- ssg: {
- preventDefault: ['/user'],
- },
- },
-});
-```
## 在自控式路由中使用
diff --git a/packages/document/docs/zh/guides/concept/entries.mdx b/packages/document/docs/zh/guides/concept/entries.mdx
index c62ae61f9a1a..29e55c67e6ae 100644
--- a/packages/document/docs/zh/guides/concept/entries.mdx
+++ b/packages/document/docs/zh/guides/concept/entries.mdx
@@ -196,12 +196,18 @@ beforeRender().then(() => {
```js title=src/entry.tsx
import React from 'react';
-import ReactDOM from 'react-dom';
+import { createRoot } from 'react-dom/client';
import App from './App';
-ReactDOM.render(, document.getElementById('root'));
+const container = document.getElementById('root');
+
+if (container) {
+ const root = createRoot(container);
+ root.render();
+}
```
+
在该模式下,**将无法使用 Modern.js 框架的运行时能力**,比如:
- 约定式路由,即基于 `src/routes` 下文件的路由
@@ -241,8 +247,6 @@ export default defineConfig({
});
```
-值得注意的是,默认情况下,Modern.js 认为通过配置指定的入口是**框架模式入口**,将自动生成真正的编译入口。如果你的应用是从 Webpack 或 Vite 等构建工具迁移到 Modern.js 框架时,你通常需要在入口配置中开启 `disableMount` 选项,此时 Modern.js 认为该入口是**构建模式入口**。
-
## 深入了解
页面入口的概念衍生自 webpack 的入口(Entrypoint)概念,其主要用于配置 JavaScript 或其他模块在应用启动时加载和执行。webpack 对于网页应用的 [最佳实践](https://webpack.docschina.org/concepts/entry-points/#multi-page-application) 通常将入口与 HTML 产物对应,即每增加一个入口最终就会在产物中生成一份对应的 HTML 文件。入口引入的模块会在编译打包后生成多个 Chunk 产物,例如对于 JavaScript 模块最终可能会生成数个类似 `dist/static/js/index.ea39u8.js` 的文件产物。
diff --git a/packages/document/docs/zh/guides/upgrade/_meta.json b/packages/document/docs/zh/guides/upgrade/_meta.json
new file mode 100644
index 000000000000..02846b13b9ca
--- /dev/null
+++ b/packages/document/docs/zh/guides/upgrade/_meta.json
@@ -0,0 +1 @@
+["overview", "config", "entry"]
diff --git a/packages/document/docs/zh/guides/upgrade/config.mdx b/packages/document/docs/zh/guides/upgrade/config.mdx
new file mode 100644
index 000000000000..bfcb70d06dcc
--- /dev/null
+++ b/packages/document/docs/zh/guides/upgrade/config.mdx
@@ -0,0 +1,579 @@
+# 配置变化
+
+本篇文档主要介绍从 Modern.js 2.0 升级到 3.0 时,配置项层面的不兼容变更以及推荐的迁移方式。
+
+## html
+
+### html.appIcon
+
+**变更内容**: 不再支持字符串形式,必须使用对象格式。
+
+**V2 类型**:
+```typescript
+type AppIconItem = {
+ src: string;
+ size: number;
+ target?: 'apple-touch-icon' | 'web-app-manifest';
+};
+
+type AppIcon = string | {
+ name?: string;
+ icons: AppIconItem[];
+ filename?: string;
+};
+```
+
+**V3 类型**:
+```typescript
+type AppIconItem = {
+ src: string;
+ size: number;
+ target?: 'apple-touch-icon' | 'web-app-manifest';
+};
+
+type AppIcon = {
+ name?: string;
+ icons: AppIconItem[];
+ filename?: string;
+};
+```
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ html: {
+ appIcon: './src/assets/icon.png',
+ },
+};
+
+// v3
+export default {
+ html: {
+ appIcon: {
+ icons: [{
+ src: './src/assets/icon.png',
+ size: 180
+ }]
+ }
+ },
+};
+```
+
+### html.xxxByEntries
+
+**变更内容**: `metaByEntries`、`templateParametersByEntries`、`injectByEntries`、`tagsByEnties`、`faviconByEntries`、`templateByEnties`、`titleByEntries` 等配置已废弃,需要使用函数语法代替。
+
+**处理步骤**:
+1. 移除相关配置
+2. 使用 `html.xxx` 的函数用法代替
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ html: {
+ metaByEntries: {
+ foo: {
+ description: 'TikTok',
+ },
+ // 其他配置...
+ },
+ },
+};
+
+// v3
+export default {
+ html: {
+ meta({ entryName }) {
+ switch (entryName) {
+ case 'foo':
+ return {
+ description: 'TikTok',
+ };
+ // 其他配置...
+ }
+ },
+ },
+};
+```
+
+### html.disableHtmlFolder
+
+**变更内容**: 该配置已废弃,使用 `html.outputStructure` 代替。
+
+**迁移示例**:
+```typescript
+// v2 - 等同于 html.outputStructure 配置为 nested
+export default {
+ html: {
+ disableHtmlFolder: true,
+ },
+};
+
+// v3
+export default {
+ html: {
+ outputStructure: 'flat',
+ },
+};
+```
+
+## output
+
+### output.overrideBrowserslist
+
+**变更内容**: 需要根据项目现有配置情况处理。
+
+**处理步骤**:
+1. 检查项目中是否有 `.browserslistrc` 文件
+2. 检查 `modern.config.[ts|js]` 中是否配置了 `output.overrideBrowserslist`
+3. 检查 package.json 中是否配置了 browserslist
+
+如果都没有,则创建 `.browserslistrc` 文件,内容为支持 ES6 的浏览器:
+
+```typescript
+chrome >= 51
+edge >= 15
+firefox >= 54
+safari >= 10
+ios_saf >= 10
+```
+
+### output.enableAssetFallback
+
+**变更内容**: 该配置已废弃,注释掉并添加说明。
+
+```typescript
+// 该配置已废弃,如有问题请咨询 oncall 解决
+// output: {
+// enableAssetFallback: true,
+// },
+```
+
+### output.cssModuleLocalIdentName
+
+**变更内容**: 该配置已废弃,使用 `output.cssModules.localIdentName` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ cssModuleLocalIdentName: '[path][name]__[local]-[hash:base64:6]',
+ },
+};
+
+// v3
+export default {
+ output: {
+ cssModules: {
+ localIdentName: '[path][name]__[local]-[hash:base64:6]',
+ },
+ },
+};
+```
+
+### output.disableCssExtract
+
+**变更内容**: 该配置已废弃,使用 `output.injectStyles` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ disableCssExtract: true,
+ },
+};
+
+// v3
+export default {
+ output: {
+ injectStyles: true,
+ },
+};
+```
+
+### output.disableFilenameHash
+
+**变更内容**: 该配置已废弃,使用 `output.filenameHash` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ disableFilenameHash: true,
+ },
+};
+
+// v3
+export default {
+ output: {
+ filenameHash: false,
+ },
+};
+```
+
+### output.disableMinimize
+
+**变更内容**: 该配置已废弃,使用 `output.minify` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ disableMinimize: true,
+ },
+};
+
+// v3
+export default {
+ output: {
+ minify: false,
+ },
+};
+```
+
+### output.disableSourceMap
+
+**变更内容**: 该配置已废弃,使用 `output.sourceMap` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ disableSourceMap: true,
+ },
+};
+
+// v3
+export default {
+ output: {
+ sourceMap: false,
+ },
+};
+```
+
+### output.enableInlineScripts
+
+**变更内容**: 该配置已废弃,使用 `output.inlineScripts` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ enableInlineScripts: true,
+ },
+};
+
+// v3
+export default {
+ output: {
+ inlineScripts: true,
+ },
+};
+```
+
+### output.enableInlineStyles
+
+**变更内容**: 该配置已废弃,使用 `output.inlineStyles` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ enableInlineStyles: true,
+ },
+};
+
+// v3
+export default {
+ output: {
+ inlineStyles: true,
+ },
+};
+```
+
+### output.enableLatestDecorators
+
+**变更内容**: 该配置已废弃,使用 `source.decorators` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ enableLatestDecorators: true,
+ },
+};
+
+// v3
+export default {
+ source: {
+ decorators: {
+ version: '2022-03',
+ },
+ },
+};
+```
+
+### output.disableNodePolyfill
+
+**变更内容**: 该配置已废弃,通过注册 `pluginNodePolyfill` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ output: {
+ disableNodePolyfill: false,
+ },
+};
+
+// v3
+import { pluginNodePolyfill } from "@rsbuild/plugin-node-polyfill";
+export default {
+ builderPlugins: [
+ pluginNodePolyfill()
+ ]
+};
+```
+
+## source
+
+### source.resolveMainFields
+
+**变更内容**: 该配置已废弃,使用 `resolve.mainFields` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+source: {
+ resolveMainFields: ['custom', 'module', 'main']
+}
+
+// v3
+resolve: {
+ mainFields: ['custom', 'module', 'main']
+}
+```
+
+### source.resolveExtensionPrefix
+
+**变更内容**: 该配置已废弃,使用 `resolve.extensions` 代替。
+
+**迁移示例**:
+```typescript
+// v2
+source: {
+ resolveExtensionPrefix: ['.ts', '.tsx', '.js']
+}
+
+// v3
+resolve: {
+ extensions: ['.ts', '.tsx', '.js']
+}
+```
+
+### source.moduleScopes
+
+**变更内容**: 该配置已废弃,直接移除。
+
+### source.enableCustomEntry
+
+**变更内容**: 该配置已废弃,直接移除。
+
+## tools
+
+### tools.esbuild
+
+**变更内容**: 该配置已废弃,需要手动切换到 esbuild 压缩。
+
+```typescript
+// 该配置已废弃,请参考 [切换压缩器](https://rsbuild.rs/zh/config/output/minify#%E5%88%87%E6%8D%A2%E5%8E%8B%E7%BC%A9%E5%99%A8) 来手动切换到 esbuild 压缩
+// tools: {
+// esbuild: { /* 配置 */ }
+// },
+```
+
+### tools.terser
+
+**变更内容**: 该配置已废弃,需要手动切换到 Terser 压缩。
+
+```typescript
+// 该配置已废弃,请参考 [切换压缩器](https://rsbuild.rs/zh/config/output/minify#%E5%88%87%E6%8D%A2%E5%8E%8B%E7%BC%A9%E5%99%A8) 来手动切换到 Terser 压缩
+// tools: {
+// terser: { /* 配置 */ }
+// },
+```
+
+### tools.devServer
+
+**变更内容 1**: `after`、`before`、`devMiddleware` 配置已废弃,使用 `dev` 配置代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ tools: {
+ devServer: {
+ before: [...],
+ after: [...],
+ devMiddleware: {
+ writeToDisk: true
+ }
+ }
+ }
+};
+
+// v3
+export default {
+ dev: {
+ setupMiddlewares: [...],
+ writeToDisk: true
+ }
+};
+```
+
+**变更内容 2**: `client`、`https`、`liveReload` 配置已废弃,使用对应的 `dev.client`、`dev.https`、`dev.liveReload` 配置代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ tools: {
+ devServer: {
+ client: {
+ port: 8081
+ }
+ }
+ }
+};
+
+// v3
+export default {
+ dev: {
+ client: {
+ port: 8081
+ }
+ }
+};
+```
+
+**变更内容 3**: `hot` 配置已废弃,使用 `dev.hmr` 配置代替。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ tools: {
+ devServer: {
+ hot: false
+ }
+ }
+};
+
+// v3
+export default {
+ dev: {
+ hmr: false
+ }
+};
+```
+
+## dev
+
+### dev.port
+
+**变更内容**: 该配置已被移除,改为 `server.port`。
+
+**迁移示例**:
+```typescript
+// 改动前
+dev: {
+ port: 8080
+}
+
+// 改动后
+server: {
+ port: process.env.NODE_ENV === 'development' && 8080
+}
+```
+
+## runtime
+
+### runtime.router
+
+**变更内容**: 不再需要,可以直接移除。
+
+### runtime.state
+
+**变更内容**: 该配置被废弃,建议使用第三方状态管理库。
+
+## experiments
+
+### experiments.lazyCompilation
+
+**变更内容**: 该配置已废弃,改为 `dev.lazyCompilation`。
+
+**迁移示例**:
+```typescript
+// v2
+experiments: {
+ lazyCompilation: true
+}
+
+// v3
+dev: {
+ lazyCompilation: true
+}
+```
+
+## plugins
+
+### app-tools 插件
+
+**变更内容**: 该插件不需要传入任何参数。
+
+**迁移示例**:
+```typescript
+// v2
+plugins: [
+ appTools({
+ bundler: 'rspack'
+ })
+],
+
+// v3
+plugins: [
+ appTools()
+],
+```
+
+## performance
+
+### performance.transformLodash
+
+**变更内容**: 不再需要,可以直接移除。
+
+**迁移示例**:
+```typescript
+// v2
+export default {
+ performance: {
+ transformLodash: true
+ }
+}
+
+// v3 - 直接移除该配置
+export default {
+ // 配置...
+}
+```
+
diff --git a/packages/document/docs/zh/guides/upgrade/entry.mdx b/packages/document/docs/zh/guides/upgrade/entry.mdx
new file mode 100644
index 000000000000..38cd9a67d9c4
--- /dev/null
+++ b/packages/document/docs/zh/guides/upgrade/entry.mdx
@@ -0,0 +1,468 @@
+# 入口变化
+
+本章节介绍 Modern.js 从 2.0 升级到 3.0 时,页面入口相关的变更内容。
+
+## 概述
+
+Modern.js 3.0 对入口机制进行了优化和简化,主要变更包括:
+
+- **入口文件命名变更**:自定义入口文件从 `index.[jt]sx` 改为 `entry.[jt]sx`
+- **Bootstrap 函数替换**:使用新的 `createRoot` 和 `render` API
+- **运行时配置迁移**:`App.config` 和 `routes/layout` 的 `config` 导出需要迁移
+- **初始化逻辑迁移**:`App.init` 和 `routes/layout` 的 `init` 导出需要改为运行时插件
+
+## 入口类型识别
+
+在开始迁移前,首先需要识别你的项目使用的入口类型。
+
+### 入口识别条件
+
+Modern.js 会扫描目录并识别符合以下**任一条件**的入口:
+
+1. **具有 `routes/` 目录** → 约定式路由入口
+2. **具有 `App.[jt]sx?` 文件** → 自控式路由入口
+3. **具有 `index.[jt]sx?` 文件(2.0)或 `entry.[jt]sx?` 文件(3.0)**→ 自定义入口
+
+### 单入口 vs 多入口
+
+**单入口应用**:默认扫描 `src/` 目录
+
+```bash
+src/
+├── routes/ # 或者
+├── App.tsx # 或者
+└── index.tsx # 2.0 版本
+```
+
+**多入口应用**:扫描 `src/` 目录下的一级子目录
+
+```bash
+src/
+├── entry1/
+│ └── routes/ # 每个子目录都是一个入口
+└── entry2/
+ └── App.tsx
+```
+
+:::tip
+你可以通过 [source.entriesDir](/configure/app/source/entries-dir) 配置修改入口扫描目录。
+:::
+
+## 迁移步骤
+
+本小节中的迁移操作都是仅当项目中实际存在对应用法时才需要执行,例如 `bootstrap` 函数、`App.config/App.init`、`routes/layout.tsx` 中的 `config/init` 函数等。
+
+### 1.自定义入口文件重命名
+
+如果你的项目使用了自定义入口文件(`index.[jt]sx`),需要将其重命名为 `entry.[jt]sx`。
+
+**2.0 版本:**
+
+```bash
+src/
+└── index.tsx
+```
+
+**3.0 版本:**
+
+```bash
+src/
+└── entry.tsx
+```
+
+### 2.Bootstrap 函数迁移
+
+如果你的入口文件导出了一个接收 `App` 和 `bootstrap` 参数的函数,需要改用新的 API。
+
+**2.0 版本:**
+
+```tsx title="src/index.tsx"
+export default (App: React.ComponentType, bootstrap: () => void) => {
+ // 执行初始化操作
+ initSomething().then(() => {
+ bootstrap();
+ });
+};
+```
+
+**3.0 版本:**
+
+```tsx title="src/entry.tsx"
+import { createRoot } from '@modern-js/runtime/react';
+import { render } from '@modern-js/runtime/browser';
+
+// 创建根组件
+const ModernRoot = createRoot();
+
+// 执行初始化操作
+async function beforeRender() {
+ await initSomething();
+}
+
+// 渲染应用
+beforeRender().then(() => {
+ render();
+});
+```
+
+:::info 说明
+- `createRoot()` 返回的组件对应 `routes/` 目录生成或 `App.tsx` 导出的组件
+- `render()` 函数用于处理渲染与挂载组件
+
+:::
+
+### 3.App.config 迁移
+
+如果你在 `App.[tj]sx` 中定义了 `App.config`,需要将其迁移到运行时配置文件中。
+
+**2.0 版本:**
+
+```tsx title="src/App.tsx"
+const App = () => {
+ return
Hello
;
+};
+
+App.config = {
+ router: {
+ supportHtml5History: true,
+ },
+};
+
+export default App;
+```
+
+**3.0 版本:**
+
+在入口同级目录创建 `modern.runtime.ts`:
+
+```ts title="src/modern.runtime.ts"
+import { defineRuntimeConfig } from '@modern-js/runtime';
+
+export default defineRuntimeConfig({
+ router: {
+ supportHtml5History: true,
+ },
+});
+```
+
+:::warning 注意
+Modern.js 3.0 不再支持在 `modern.config.ts` 中配置 runtime,必须使用 `modern.runtime.ts` 文件。
+:::
+
+### 4.App.init 迁移
+
+如果你在 `App.[tj]sx` 中定义了 `App.init`,需要将其改为运行时插件。
+
+**2.0 版本:**
+
+```tsx title="src/App.tsx"
+const App = () => {
+ return Hello
;
+};
+
+App.init = (context) => {
+ context.store = createStore();
+ context.request = (url: string) => fetch(url);
+};
+
+export default App;
+```
+
+**3.0 版本:**
+
+```ts title="src/modern.runtime.ts"
+import type { RuntimePlugin } from '@modern-js/runtime';
+import { defineRuntimeConfig } from '@modern-js/runtime';
+
+const initPlugin = (): RuntimePlugin => ({
+ name: 'init-plugin',
+ setup: (api) => {
+ return {
+ init({ context }) {
+ context.store = createStore();
+ context.request = (url: string) => fetch(url);
+ },
+ };
+ },
+});
+
+export default defineRuntimeConfig({
+ plugins: [initPlugin()],
+});
+```
+
+### 5.routes/layout.tsx 中的 config 导出迁移
+
+如果你在 `routes/layout.tsx` 中导出了 `config` 函数,需要将其迁移到运行时配置文件。
+
+**2.0 版本:**
+
+```tsx title="src/routes/layout.tsx"
+export const config = () => {
+ return {
+ router: {
+ supportHtml5History: true,
+ },
+ };
+};
+
+export default function Layout() {
+ return ;
+}
+```
+
+**3.0 版本:**
+
+```tsx title="src/routes/layout.tsx"
+export default function Layout() {
+ return ;
+}
+```
+
+```ts title="src/modern.runtime.ts"
+import { defineRuntimeConfig } from '@modern-js/runtime';
+
+export default defineRuntimeConfig({
+ router: {
+ supportHtml5History: true,
+ },
+});
+```
+
+### 6.routes/layout.tsx 中的 init 导出迁移
+
+如果你在 `routes/layout.tsx` 中导出了 `init` 函数,需要将其改为运行时插件。
+
+**2.0 版本:**
+
+```tsx title="src/routes/layout.tsx"
+export const init = (context) => {
+ context.request = (url: string) => fetch(url);
+};
+
+export default function Layout() {
+ return ;
+}
+```
+
+**3.0 版本:**
+
+```tsx title="src/routes/layout.tsx"
+export default function Layout() {
+ return ;
+}
+```
+
+```ts title="src/modern.runtime.ts"
+import type { RuntimePlugin } from '@modern-js/runtime';
+import { defineRuntimeConfig } from '@modern-js/runtime';
+
+const initPlugin = (): RuntimePlugin => ({
+ name: 'init-plugin',
+ setup: (api) => {
+ return {
+ init({ context }) {
+ context.request = (url: string) => fetch(url);
+ },
+ };
+ },
+});
+
+export default defineRuntimeConfig({
+ plugins: [initPlugin()],
+});
+```
+
+
+## 多入口应用迁移注意事项
+
+对于多入口应用,需要在 `src/modern.runtime.ts` 中使用函数形式的配置,根据入口名称返回不同的运行时配置。
+
+### 配置方式
+
+**目录结构:**
+
+```bash
+src/
+├── modern.runtime.ts # 统一的运行时配置文件
+├── entry1/
+│ └── routes/
+└── entry2/
+ └── App.tsx
+```
+
+**配置示例:**
+
+```ts title="src/modern.runtime.ts"
+import { defineRuntimeConfig } from '@modern-js/runtime';
+
+export default defineRuntimeConfig((entryName) => {
+ // 公共配置
+ const commonConfig = {
+ plugins: [commonPlugin()],
+ };
+
+ // 根据入口名称返回特定配置
+ if (entryName === 'entry1') {
+ return {
+ ...commonConfig,
+ router: {
+ supportHtml5History: true,
+ },
+ plugins: [
+ ...commonConfig.plugins,
+ entry1Plugin(),
+ ],
+ };
+ }
+
+ if (entryName === 'entry2') {
+ return {
+ ...commonConfig,
+ router: {
+ supportHtml5History: false,
+ },
+ plugins: [
+ ...commonConfig.plugins,
+ entry2Plugin(),
+ ],
+ };
+ }
+
+ // 默认配置
+ return commonConfig;
+});
+```
+
+:::info 说明
+- `entryName` 参数对应入口目录名称
+- 主入口(与 `package.json` 中 `name` 同名):传入的是该目录名
+- 其他入口:传入的是入口目录名
+
+:::
+
+### 迁移注意事项
+
+1. **合并同一入口的配置**:如果同一入口下同时存在 `App.config/App.init` 和 `routes/layout.tsx` 的 `config/init`,需要将它们合并到 `src/modern.runtime.ts` 文件中对应入口的配置里
+
+2. **多个插件并列配置**:多个运行时插件可以在 `plugins` 数组中并列配置
+
+3. **清理旧代码**:迁移完成后,记得删除原文件中的:
+ - `App.config` 属性
+ - `App.init` 方法
+ - `routes/layout.tsx` 中的 `config` 导出
+ - `routes/layout.tsx` 中的 `init` 导出
+
+### 迁移示例
+
+假设你有一个 2.0 版本的多入口应用:
+
+**2.0 版本目录结构:**
+
+```bash
+src/
+├── main/
+│ ├── routes/
+│ │ └── layout.tsx # 含 config 和 init
+│ └── App.tsx # 含 App.config 和 App.init
+└── admin/
+ └── routes/
+ └── layout.tsx # 含 config 和 init
+```
+
+**2.0 版本配置:**
+
+```tsx title="src/main/App.tsx"
+const App = () => Main App
;
+
+App.config = {
+ router: { supportHtml5History: true },
+};
+
+App.init = (context) => {
+ context.mainData = 'main';
+};
+```
+
+```tsx title="src/admin/routes/layout.tsx"
+export const config = () => ({
+ router: { supportHtml5History: false },
+});
+
+export const init = (context) => {
+ context.adminData = 'admin';
+};
+```
+
+**3.0 版本迁移后:**
+
+```bash
+src/
+├── modern.runtime.ts # 新增统一配置文件
+├── main/
+│ ├── routes/
+│ │ └── layout.tsx # 移除 config 和 init
+│ └── App.tsx # 移除 App.config 和 App.init
+└── admin/
+ └── routes/
+ └── layout.tsx # 移除 config 和 init
+```
+
+```ts title="src/modern.runtime.ts"
+import { defineRuntimeConfig } from '@modern-js/runtime';
+import type { RuntimePlugin } from '@modern-js/runtime';
+
+// main 入口的初始化插件
+const mainInitPlugin = (): RuntimePlugin => ({
+ name: 'main-init-plugin',
+ setup: (api) => {
+ return {
+ init({ context }) {
+ context.mainData = 'main';
+ },
+ };
+ },
+});
+
+// admin 入口的初始化插件
+const adminInitPlugin = (): RuntimePlugin => ({
+ name: 'admin-init-plugin',
+ setup: (api) => {
+ return {
+ init({ context }) {
+ context.adminData = 'admin';
+ },
+ };
+ },
+});
+
+export default defineRuntimeConfig((entryName) => {
+ if (entryName === 'main') {
+ return {
+ router: {
+ supportHtml5History: true,
+ },
+ plugins: [mainInitPlugin()],
+ };
+ }
+
+ if (entryName === 'admin') {
+ return {
+ router: {
+ supportHtml5History: false,
+ },
+ plugins: [adminInitPlugin()],
+ };
+ }
+
+ return {};
+});
+```
+
+## 相关链接
+
+- [页面入口](/guides/concept/entries)
+- [运行时配置](/configure/app/runtime/0-intro)
+- [Runtime 插件](/plugin/introduction.html#runtime-插件)
+- [source.entries 配置](/configure/app/source/entries)
+- [source.entriesDir 配置](/configure/app/source/entries-dir)
diff --git a/packages/document/docs/zh/guides/upgrade/overview.mdx b/packages/document/docs/zh/guides/upgrade/overview.mdx
new file mode 100644
index 000000000000..dc75ec8ca8ed
--- /dev/null
+++ b/packages/document/docs/zh/guides/upgrade/overview.mdx
@@ -0,0 +1,36 @@
+# 概述
+
+本文档将帮助您从 Modern.js 2.0 升级到 Modern.js 3.0。
+
+## 升级概览
+
+Modern.js 3.0 带来了多项重大改进和变化,主要包括:
+
+- **构建工具升级**:默认使用 [Rspack](https://rspack.dev) 构建,不再支持 Webpack,构建配置与 [Rsbuild](https://rsbuild.dev) 对齐。
+- **React 生态升级**:全面支持 [React 19](https://react.dev/blog/2024/04/25/react-19) 和 [React Router v7](https://reactrouter.com)。
+- **插件系统重构**:重新设计插件 API,支持在 CLI、Runtime、Server 层通过自定义插件扩展框架能力。
+- **React Server Component**:支持在 [CSR](/guides/get-started/glossary#csr) 和 [SSR](/guides/basic-features/render/ssr) 项目中使用 React Server Component。
+- **国际化增强**:提供开箱即用的 [i18n 插件](/guides/advanced-features/international),简化国际化开发流程。
+- **SSG 能力完善**:提供完整的[静态站点生成(SSG)](/guides/basic-features/render/ssg)支持。
+- **路由配置增强**:支持[配置式路由](/guides/basic-features/routes/config-routes),可单独使用或与[约定式路由](/guides/basic-features/routes/routes)结合,提供更灵活的路由定义方式。
+
+
+## 升级前置检查
+
+在开始升级之前,请确认:
+
+1. 当前项目使用的是 Modern.js 2.0
+2. 确定使用的 react 版本是 17 及以上
+2. 确定使用的 node.js 版本是 18.20.8 及以上,推荐使用 node.js 22 以上版本
+
+
+## 获取帮助
+
+如果在升级过程中遇到任何问题,您可以通过以下方式获取帮助:
+
+- 查阅 [Modern.js 官方文档](https://modernjs.dev)
+- 在 [GitHub Issues](https://github.com/web-infra-dev/modern.js/issues) 中搜索相关问题或提交新的 issue
+- 加入 [Modern.js Discord 社区](https://discord.gg/modernjs)与其他开发者交流
+
+我们建议在提交 issue 时提供尽可能详细的信息,包括错误日志、配置文件和复现步骤,以便更快地解决问题
+