WebInfra
前端 @字節跳動 Web Infra
Modern.js 2.0 發布 至今,已過去三年時間,感謝社區開發者們對 Modern.js 的使用和信任。Modern.js 一直保持穩定的迭代,累計發布了超過 100 個版本。
在字節內部,Modern.js 已成為 Web 開發的核心框架。在全公司活躍的 Web 項目中,使用佔比已從 2025 年初的 40% 增長至目前接近 70%。
這三年中,我們不斷擴充新特性,持續進行代碼重構與優化,也收到了非常多的反饋,這些經驗成為了 3.0 版本改進的重要參考。經過慎重考慮,我們決定發布 Modern.js 3.0,對框架進行一次全面的升級。
從 Modern.js 2.0 到 3.0,有兩個核心轉變:
更聚焦,專注於 Web 框架
更開放,積極面向社區工具
TL;DR:Modern.js 3.0 集成 React Server Component,支持 CSR 和 SSR 項目,並支持漸進式遷移。

React Server Components(服務端組件)是一種新的組件類型,它允許組件邏輯完全在服務端執行,並直接將渲染後的 UI 流式傳輸到客戶端。與傳統的客戶端組件相比,服務端組件帶來了以下特性:
| 特性 | 說明 |
|---|---|
| 零客戶端包體積 | 組件代碼不包含在客戶端 JS Bundle 中,僅在服務端執行,加快首屏加載與渲染速度 |
| 更高的內聚性 | 組件可直接連接資料庫、調用內部 API、讀取本地文件,提高開發效率 |
| 漸進增強 | 可與客戶端組件無縫混合使用,按需下放交互邏輯到客戶端,在保持高性能的同時,支持複雜交互體驗 |
需要明確的是,RSC 和 SSR 是截然不同的概念:
兩者可以組合使用:Server Component 可以在 SSR 項目下使用,也可以在 CSR 項目下使用。在 Modern.js 3.0 中,我們同時支持這兩種模式,開發者可以根據需求選擇。

在 Modern.js 3.0 中,只需在配置中啟用 RSC 能力:
modern.config.ts
export default defineConfig({
server: {
rsc: true,
}
});
配置啟用後,所有的路由組件都會默認成為 Server Component。項目中可能存在無法在服務端運行的組件,你可以先為這些組件添加
'use client'標記,以保持原有行為,再逐步遷移。
RSC 效果演示視頻:lf3-static.bytednsdoc.com/obj/eden-cn…
Modern.js 一直選擇 React Router 作為路由解決方案。去年,React Router v7 宣布支持 React Server Component,這為 Modern.js 提供了在 SPA 應用下實現 RSC 的基礎。
相比於社區其他框架,Modern.js 對 RSC 做了幾點優化:
基於靈活的組件邊界控制能力,Modern.js 3.0 提供了漸進式的遷移方式。Modern.js 3.0 允許基於路由組件維度的 Server Component 遷移,無需遷移整條組件樹鏈路。

更多 React Server Component 的詳細內容,可以參考:React Server Component
TL;DR:Modern.js 3.0 移除了對 webpack 的支持,全面擁抱 Rspack,並升級到最新的 Rspack & Rsbuild 2.0。
在 2023 年,我們開源了 Rspack,並在 Modern.js 中支持將 Rspack 作為可選的打包工具。在字節內部,超過 60% 的 Modern.js 項目已經切換到 Rspack 構建。
經過兩年多發展,Rspack 在社區中的月下載量已超過 1000 万次,成為行業內被廣泛使用的打包工具;同時,Modern.js 的 Rspack 構建模式也得到持續完善。

在 Modern.js 3.0 中,我們決定移除對 webpack 的支持,從而使 Modern.js 變得更加輕量和高效,並能更充分地利用 Rspack 的新特性。
Modern.js 3.0 在移除 webpack 後,能夠更好地遵循 Rspack 最佳實踐,在構建性能、安裝速度等方面均有提升:
底層依賴升級
Modern.js 3.0 將底層依賴的 Rspack 和 Rsbuild 升級至 2.0 版本,並基於新版本優化了默認構建配置,使整體行為更加一致。
參考以下文檔了解底層行為變化:
更快的構建速度
Modern.js 通過 Rspack 的多項特性來減少構建耗時:
更快的安裝速度
移除 webpack 相關依賴後,Modern.js 3.0 的構建依賴數量和體積均明顯減少:
Modern.js 現在默認啟用 Rspack 的多項產物優化策略,能夠比 webpack 生成更小的產物體積,例如:
增強 Tree shaking
增強了 tree shaking 分析能力,可以處理更多動態導入語法,例如解構賦值:
// 參數中的解構訪問
import('./module').then(({ value }) => {
console.log(value);
});
// 函數體內的解構訪問
import('./module').then((mod) => {
const { value } = mod;
console.log(value);
});
常量內聯
對常量進行跨模塊內聯,有助於壓縮工具進行更準確的靜態分析,從而消除無用的代碼分支:
// constants.js
export const ENABLED = true;
// index.js
import { ENABLED } from './constants';
if (ENABLED) {
doSomething();
} else {
doSomethingElse();
}
// 構建產物 - 無用分支被消除
doSomething();
TL;DR:Modern.js 3.0 正式開放完整插件體系,提供運行時、服務端插件,同時支持靈活處理應用入口。
Modern.js 2.0 提供了 CLI 插件與內測版本的運行時插件,允許開發者對項目進行擴展。但在實踐過程中,我們發現現有的能力不足以支撐複雜的業務場景。
Modern.js 3.0 提供了更靈活的定制能力,允許為應用編寫全流程的插件,幫助團隊統一業務邏輯、減少重複代碼:
運行時插件在 CSR 與 SSR 過程中都會運行,新版本提供了兩個核心鉤子:
onBeforeRender:在渲染前執行邏輯,可用於數據預取、注入全局數據wrapRoot:封裝根組件,添加全局 Provider、佈局組件等你可以在 src/modern.runtime.ts 中註冊插件,相比在入口手動引入高階組件,運行時插件可插拔、易更新,在多入口場景下無需重複引入:
src/modern.runtime.tsx
import { defineRuntimeConfig } from "@modern-js/runtime";
export default defineRuntimeConfig({
plugins: [
{
name: "my-runtime-plugin",
setup: (api) => {
api.onBeforeRender((context) => {
context.globalData = { theme: "dark" };
});
api.wrapRoot((App) => (props) => <App {...props} />);
},
},
],
});
更多 Runtime 插件使用方式,請查看文檔:Runtime 插件
在實踐過程中我們發現,部分項目需要擴展 Web Server,例如鑒權、數據預取、降級處理、動態 HTML 腳本注入等。
在 Modern.js 3.0 中,我們使用 Hono 重構了 Web Server,並正式開放了服務端中間件與插件的能力。開發者可以使用 Hono 的中間件來完成需求:
server/modern.server.ts
import { defineServerConfig, type MiddlewareHandler } from "@modern-js/server-runtime";
const timingMiddleware: MiddlewareHandler = async (c, next) => {
const start = Date.now();
await next();
const duration = Date.now() - start;
c.header('X-Response-Time', `${duration}ms`);
};
const htmlMiddleware: MiddlewareHandler = async (c, next) => {
await next();
const html = await c.res.text();
const modified = html.replace(
"<head>",
'<head><meta name="generator" content="Modern.js">'
);
c.res = c.body(modified, { status: c.res.status, headers: c.res.headers });
};
export default defineServerConfig({
middlewares: [timingMiddleware],
renderMiddlewares: [htmlMiddleware],
});
更多服務端插件使用方式,可以查看文檔:自定義 Web Server
在 Modern.js 3.0 中,我們重構了自定義入口,相比於舊版 API 更加清晰靈活:
src/entry.tsx
import { createRoot } from '@modern-js/runtime/react';
import { render } from '@modern-js/runtime/browser';
const ModernRoot = createRoot();
async function beforeRender() {
// 渲染前的異步操作,如初始化 SDK、獲取用戶信息等
}
beforeRender().then(() => {
render(<ModernRoot />);
});
更多入口使用方式,請查看文檔:入口
TL;DR:Modern.js 3.0 內置 React Router v7,提供配置式路由能力與 AI 友好的調試方式。
在 Modern.js 3.0 中,我們統一升級到 React Router v7,並廢棄了對 v5 和 v6 的內置支持。這一決策基於以下考慮:
版本演進與穩定性
React Router v6 是一個重要的過渡版本,它引入了許多新特性(如數據加載、錯誤邊界等)。而 v7 在保持 v6 API 兼容性的基礎上,進一步優化了性能、穩定性和開發體驗。隨著 React Router 團隊將 Remix 定位為獨立框架,React Router 核心庫可能會在 v7 版本上長期維護,使其成為更可靠的選擇。
升級路徑
在 Modern.js 中,我們推薦使用約定式路由來組織代碼。但在實際業務中,開發者偶爾遇到以下場景:
因此,Modern.js 3.0 提供了完整的配置式路由支持,可以與約定式路由一起使用,或兩者分別單獨使用。
src/modern.routes.ts
import { defineRoutes } from "@modern-js/runtime/config-routes";
export default defineRoutes(({ route, layout, page }) => {
return [
route("home.tsx", "/"),
route("about.tsx", "about"),
route("blog.tsx", "blog/:id"),
];
});
更多配置式路由使用方式,請查看文檔:配置式路由
運行 npx modern routes 命令即可在 dist/routes-inspect.json 文件中生成完整的路由結構分析報告。
報告中會顯示每個路由的路徑、組件文件、數據加載器、錯誤邊界、Loading 組件等完整信息,幫助開發者快速了解項目的路由配置,快速定位和排查路由相關問題。結構化的 JSON 格式也便於 AI agent 理解和分析路由結構,提升 AI 輔助開發的效率。
具體使用方式,請查看文檔:路由調試
TL;DR:Modern.js 3.0 重做了 SSG 能力,提供了靈活的緩存能力,對降級策略也進行了進一步的完善。
在 Modern.js 2.0 中,我們提供了靜態站點生成的能力。這個能力非常適合用在可以靜態渲染的頁面中,能極大的提升頁面首屏性能。
在新版本中,我們對 SSG 進行了重新設計:
在新版本中,你可以通過 data loader 進行數據獲取,與非 SSG 場景保持一致。然後在 ssg.routes 配置中即可直接指定要渲染的路由:
modern.config.ts
export default defineConfig({
output: {
ssg: {
routes: ['/blog'],
},
},
});
routes/blog/page.data.ts
export const loader = async () => {
const articles = await fetchArticles();
return { articles };
};
更多 SSG 的使用方式,請查看文檔:SSG
Modern.js 3.0 中提供了不同維度的緩存機制,幫助項目提升首屏性能。所有緩存均支持靈活配置,比如可以支持類似 HTTP 的 stale-while-revalidate 策略:
渲染緩存
支持將 SSR 結果進行整頁的緩存,在 server/cache.ts 中配置:
server/cache.ts
import type { CacheOption } from '@modern-js/server-runtime';
export const cacheOption: CacheOption = {
maxAge: 500, // ms
staleWhileRevalidate: 1000, // ms
};
使用渲染緩存,請查看文檔:渲染緩存
數據緩存
我們在新版本中提供了 cache 函數,相比渲染緩存它提供了更精細的數據粒度控制。當多個數據請求依賴同一份數據時,cache 可以避免重複請求:
server/loader.ts
import { cache } from "@modern-js/runtime/cache";
import { fetchUserData, fetchUserProjects, fetchUserTeam } from "./api";
// 緩存用戶數據,避免重複請求
const getUser = cache(fetchUserData);
const getProjects = async () => {
const user = await getUser("test-user");
return fetchUserProjects(user.id);
};
const getTeam = async () => {
const user = await getUser("test-user"); // 复用緩存,不會重複請求
return fetchUserTeam(user.id);
};
export const loader = async () => {
// getProjects 和 getTeam 都依賴 getUser,但 getUser 只會執行一次
const [projects, team] = await Promise.all([getProjects(), getTeam()]);
return { projects, team };
};
更多數據緩存的使用方式,請查看文檔:數據緩存
在實踐過程中,我們沉澱了多維度的降級策略:
| 類型 | 觸發方式 | 降級行為 | 使用場景 |
|---|---|---|---|
| 異常降級 | Data Loader 執行報錯 | 觸發 ErrorBoundary | 數據請求異常兜底 |
| 組件渲染報錯 | 服務端渲染異常 | 降級到 CSR,複用已有數據渲染 | 服務端渲染異常兜底 |
| 業務降級 | Loader 抛出 throw Response |
觸發 ErrorBoundary,返回對應 HTTP 狀態碼 | 404、權限校驗等業務場景 |
| 配置 Client Loader | 配置 Client Loader | 繞過 SSR,直接請求數據源 | 需要在客戶端直接獲取數據的場景 |
| 強制降級 | Query 參數 ?__csr=true |
跳過 SSR,返回 CSR 頁面 | 調試、臨時降級 |
| 強制降級 | 請求頭 x-modern-ssr-fallback |
跳過 SSR,返回 CSR 頁面 | 門檻層控制降級 |
TL;DR:Modern.js 3.0 基於 Hono 重構了 Web Server,提供基於 Hono 的一體化函數,同時支持跨項目調用。
在 Modern.js 3.0 中,我們使用 Hono 作為 BFF 的運行時框架,開發者可以基於 Hono 生態擴展 BFF Server,享受 Hono 輕量、高性能的優勢。
通過 useHonoContext 可以獲取完整的 Hono 上下文,訪問請求信息、設置響應頭等:
api/lambda/user.ts
import { useHonoContext } from '@modern-js/server-runtime';
export const get = async () => {
const c = useHonoContext();
const token = c.req.header('Authorization');
c.header('X-Custom-Header', 'modern-js');
const id = c.req.query('id');
return { userId: id, authenticated: !!token };
};
在過去,Modern.js BFF 只能在當前項目中使用,而我們陸續收到開發者反饋,希望能夠在不同項目中使用。這大多數情況是由於開發者的遷移成本、運維成本造成的,相比於抽出原有代碼再部署一個,顯然複用已有服務更加合理。
為了保證開發者能得到與當前項目一體化調用類似的體驗,我們提供了跨項目調用的能力。
更多 BFF 的使用方式,請查看文檔:BFF
TL;DR:Modern.js 3.0 與 Module Federation 2.0 深度集成,支持 MF SSR 和應用級別模塊導出。
Modern.js 3.0 支持在 SSR 應用中使用 Module Federation,組合使用模塊聯邦和服務端渲染能力,為用戶提供更好的首屏性能體驗。
modern.config.ts
export default defineConfig({
server: {
ssr: {
mode: 'stream',
},
},
});
結合 Module Federation 的數據獲取能力,每個遠程模塊都可以定義自己的數據獲取邏輯:
src/components/Button.data.ts
export const fetchData = async () => {
return {
data: `Server time: ${new Date().toISOString()}`,
};
};
src/components/Button.tsx
export const Button = (props: { mfData: { data: string } }) => {
return <button>{props.mfData?.data}</button>;
};
不同於傳統的組件級別共享,Modern.js 3.0 支持導出應用級別模塊——具備完整路由能力、可以像獨立應用一樣運行的模塊。這是微前端場景中的重要能力。
生產者導出應用
src/export-App.tsx
import '@modern-js/runtime/registry/index';
import { render } from '@modern-js/runtime/browser';
import { createRoot } from '@modern-js/runtime/react';
import { createBridgeComponent } from '@module-federation/modern-js/react';
const ModernRoot = createRoot();
export const provider = createBridgeComponent({
rootComponent: ModernRoot,
render: (Component, dom) => render(Component, dom),
});
export default provider;
消費者加載應用
src/routes/remote/$.tsx
import { createRemoteAppComponent } from '@module-federation/modern-js/react';
import { loadRemote } from '@module-federation/modern-js/runtime';
const RemoteApp = createRemoteAppComponent({
loader: () => loadRemote('remote/app'),
fallback: ({ error }) => <div>Error: {error.message}</div>,
loading: <div>Loading...</div>,
});
export default RemoteApp;
通過通配路由 $.tsx,所有訪問 /remote/* 的請求都會進入遠程應用,遠程應用內部的路由也能正常工作。
更多 Module Federation 的使用方式,請查看文檔:Module Federation
TL;DR:Modern.js 3.0 升級 React 19,最低支持 Node.js 20。
Modern.js 3.0 新項目默認使用 React 19,最低支持 React 18。
如果你的項目仍在使用 React 16 或 React 17,請先參考 React 19 官方升級指南 完成版本升級。
隨著 Node.js 不斷推進版本演進,Node.js 18 已經 EOL。在 Modern.js 3.0 中,推薦使用 Node.js 22 LTS,不再保證對 Node.js 18 的支持。
在 Modern.js 3.0 中,我們基於 Storybook Rsbuild 實現了使用 Storybook 構建 Modern.js 應用。
通過 Storybook Addon,我們將 Modern.js 配置轉換合併為 Rsbuild 配置,並通過 Storybook Rsbuild 驅動構建,讓 Storybook 調試與開發命令保持配置對齊。
更多 Storybook 使用方式,請查看文檔:使用 Storybook
升級 Modern.js 3.0 意味著擁抱更輕量、更標準的現代化開發範式。通過全面對齊 Rspack 與 React 19 等主流生態,徹底解決歷史包袱帶來的維護痛點,顯著提升構建與運行性能。
未來,我們也會基於 Modern.js 3.0 提供更多的 AI 集成與最佳實踐,配合靈活的全棧插件系統,讓開發者能以極低的學習成本複用社區經驗,實現開發效率的質變與應用架構的現代化升級。
更多改進與變更,請查看文檔:升級指南
最後,再次感謝每一位給予我們反饋和支持的開發者,我們將繼續與大家保持溝通,在相互支持中共同成長。
如果你在使用過程中遇到問題,歡迎通過以下方式反饋: