# Modern.js
> The Modern.js framework is a progressive web framework based on React. At ByteDance, we use Modern.js to build upper-level frameworks that have supported the development of thousands of web applications.
## 指南
- [介绍](/zh/guides/get-started/introduction.md): Modern.js 是一个基于 React 的渐进式 Web 开发框架。在字节跳动内部,我们将 Modern.js 封装为上层框架,并支撑了数千个 Web 应用的研发。 Modern.js 能为开发者提供极致的开发体验(Development Experience),让应用拥有更好的用户体验(User Experience)。 在开发 React 应用过程中,开发者通常需要去为某些功能去设计实现方案,或是使用其他的库、框架来解决这些问题。Modern.js 支持 React 应用所需要的所有配置和工具,并内置额外的功能和优化。开发者可以使用 React 构建应用的 UI,然后逐步采用 Modern.js 的功能来解决常见的应用需求,如路由、数据获取、状态管理等。 它主要包含以下特性: 🚀 Rust 构建:Modern.js 使用 Rsbuild/Rspack 作为构建工具,编译飞快。🪜 渐进式:使用最精简的模板创建项目,通过生成器逐步开启插件功能,定制解决方案。🏠 一体化:开发与生产环境 Web Server 逻辑一致,CSR 和 SSR 同构开发,函数即接口的 API 服务调用。🕸 约定式路由:使用基于文件约定的路由,帮助开发者快速搭建应用。
- [快速上手](/zh/guides/get-started/quick-start.md)
- [版本升级](/zh/guides/get-started/upgrade.md)
- [名词解释](/zh/guides/get-started/glossary.md)
- [技术栈](/zh/guides/get-started/tech-stack.md): Modern.js 框架默认集成了一些社区中流行的库和开发工具。 在这篇文档中,你可以了解到 Modern.js 框架涉及的主要技术栈,以及一些可选的库和工具。
- [AI 工具](/zh/guides/get-started/ai-coding-agents.md): Modern.js 为 AI Agent 提供了一套工具套件,让项目开箱即为 agent-ready,帮助你更准确、高效地用 AI 完成 Modern.js 应用的开发、升级与迁移。
- [页面入口](/zh/guides/concept/entries.md): 通过本章节,你可以了解到 Modern.js 中的入口约定,以及如何自定义入口。
- [构建工具](/zh/guides/concept/builder.md): Modern.js 构建是基于 Rsbuild 实现的,使用 Rspack 作为打包工具。
- [Web 服务器](/zh/guides/concept/server.md): Modern.js 为应用提供了内置的 Web 服务器,可以被运行在任何拥有 Node.js 的容器环境中。无论是在本地开发环境中执行 dev 命令,或是执行 build && serve 命令运行生成环境产物,或是官方的部署方案,都是通过这个 Web 服务器来托管应用。
- [路由基础](/zh/guides/basic-features/routes/routes.md): Modern.js 的路由基于 React Router 7,提供了基于文件约定的路由能力,并支持了业界流行的约定式路由模式:嵌套路由。当入口被识别为 约定式路由 时,Modern.js 会自动基于文件系统,生成对应的路由结构。
- [配置式路由](/zh/guides/basic-features/routes/config-routes.md): 默认情况下,Modern.js 推荐使用 约定式路由 作为路由定义的方式。同时,Modern.js 也提供了一个配置式路由的能力,其可以和约定式路由一起使用,或两者分别单独使用。
- [数据获取](/zh/guides/basic-features/data/data-fetch.md): Modern.js 中提供了开箱即用的数据获取能力,开发者可以通过这些 API,在项目中获取数据。需要注意的是,这些 API 并不帮助应用发起请求,而是帮助开发者更好地管理数据,提升项目的性能。
- [数据写入](/zh/guides/basic-features/data/data-write.md): 在数据获取章节中,介绍了 Modern.js 获取数据的方式,你可能会遇到两个问题: 如何更新 Data Loader 返回的数据?如何将新的数据传递到服务器? 在 Modern.js 中,可以通过 Data Action 解决和实现。
- [数据缓存](/zh/guides/basic-features/data/data-cache.md): cache 函数可以让你缓存数据获取或计算的结果,相比整页渲染缓存,它提供了更精细的数据粒度控制,并且适用于客户端渲染(CSR)、服务端渲染(SSR)、API 服务(BFF)等多种场景。
- [渲染模式总览](/zh/guides/basic-features/render/overview.md): Modern.js 支持多种渲染模式,不同的渲染模式适用于不同的场景。选择合适的渲染模式可以显著提升应用的性能和用户体验。
- [服务端渲染(SSR)](/zh/guides/basic-features/render/ssr.md): 服务端渲染(Server-Side Rendering,简称 SSR)在服务器端生成完整的 HTML 页面,然后发送到浏览器端直接显示,无需客户端额外渲染。
- [服务端流式渲染(Streaming SSR)](/zh/guides/basic-features/render/streaming-ssr.md): 流式渲染是一种先进的渲染方式,它可以在页面渲染过程中逐步返回内容,从而显著提升用户体验。 在传统的 SSR 渲染方式中,页面的渲染是一次性完成的,需要等待所有数据加载完成后才能返回完整的 HTML。而在流式渲染中,页面的渲染是逐步完成的,可以边渲染边返回,用户能够更快地看到初始内容。 相比传统 SSR 渲染: 更快感知速度:流式渲染可以在渲染过程中逐步显示内容,能够以最快的速度显示业务首页更好的用户体验:通过流式渲染,用户可以更快地看到页面上的内容,而不需要等待整个页面都渲染完成后才能交互更好的性能控制:流式渲染可以让开发者更好地控制页面加载的优先级和顺序,从而更好地优化性能和用户体验更好的适应性:流式渲染可以更好地适应不同网络速度和设备性能,使得页面在各种环境下都能有更好的表现
- [渲染缓存](/zh/guides/basic-features/render/ssr-cache.md): 在开发应用时,有时我们会将计算结果进行缓存,例如使用 React useMemo、useCallback 等 Hook。通过缓存我们可以减少计算的次数来减少 CPU 资源占用,提高用户体验。 Modern.js 支持将服务器端渲染(SSR)结果进行缓存,减少服务器每次请求时的计算和渲染时间,从而加速页面加载速度,提高用户体验。同时,缓存也能降低服务端负载,节省计算资源,提高用户访问速度。
- [静态站点生成(SSG)](/zh/guides/basic-features/render/ssg.md): SSG(Static Site Generation)是一种基于数据与模板,在构建时渲染完整静态网页的技术解决方案。这意味着在生产环境中,页面默认就是有内容的,并且可以被 CDN 缓存。对于无需数据的页面,SSG 可以提供更好的性能和更高的安全性。
- [React Server Components (RSC)](/zh/guides/basic-features/render/rsc.md): React Server Components (RSC) 是一种新的组件类型,允许在服务端环境中渲染组件,为现代 Web 应用带来更好的性能和开发体验。
- [渲染预处理](/zh/guides/basic-features/render/before-render.md): 在某些场景下,应用需要在渲染前执行预处理操作。Modern.js 推荐使用 Runtime 插件 (Runtime Plugin) 来实现这类逻辑。
- [引入 CSS](/zh/guides/basic-features/css/css.md): Modern.js 内置多种常用的 CSS 开发方案,包括 Less / Sass / Stylus 预处理器、PostCSS、CSS Modules、CSS-in-JS 和 Tailwind CSS。
- [使用 CSS Modules](/zh/guides/basic-features/css/css-modules.md): CSS Modules 让我们能以模块化的方式编写 CSS 代码,并且可以在 JavaScript 文件中导入和使用这些样式。使用 CSS Modules 可以自动生成唯一的类名,隔离不同模块之间的样式,避免类名冲突。 Modern.js 默认支持使用 CSS Modules,无需添加额外的配置。我们约定使用 [name].module.css 文件名来启用 CSS Modules。 以下样式文件会被视为 CSS Modules: *.module.scss*.module.less*.module.css
- [使用 CSS-in-JS](/zh/guides/basic-features/css/css-in-js.md): CSS-in-JS 是一种可以将 CSS 样式写在 JS 文件里的技术。 Modern.js 支持社区常用的 CSS-in-JS 实现库 styled-components,它使用 JavaScript 的新特性 Tagged template 编写组件的 CSS 样式。 Modern.js 插件 @modern-js/plugin-styled-components 提供了对 styled-components 的支持,并为 styled-components 添加了服务器端渲染能力。你可以通过安装 @modern-js/plugin-styled-components 插件来使用 styled-components。
- [使用 Tailwind CSS](/zh/guides/basic-features/css/tailwindcss.md): Tailwind CSS 是一个以 Utility Class 为基础的 CSS 框架和设计系统,可以快速地为组件添加常用样式,同时支持主题样式的灵活扩展。
- [HTML 模板](/zh/guides/basic-features/html.md): Modern.js 提供了 JSX 语法和 HTML(EJS) 语法两种方式用于自定义 HTML 模板。
- [引用静态资源](/zh/guides/basic-features/static-assets.md): Modern.js 支持在代码中引用图片、字体、媒体类型的静态资源。
- [引用 JSON 文件](/zh/guides/basic-features/static-assets/json-files.md): Modern.js 默认支持在代码中引用 JSON 文件。可以通过 Rsbuild 插件来支持引用 YAML 和 TOML 文件并将其转换为 JSON 格式。
- [引用 SVG 资源](/zh/guides/basic-features/static-assets/svg-assets.md): Modern.js 支持在代码中引用 SVG 资源,并将 SVG 图片转换为 React 组件或 URL。
- [引用 Wasm 资源](/zh/guides/basic-features/static-assets/wasm-assets.md): Modern.js 支持在代码引用 WebAssembly 资源。
- [数据模拟(Mock)](/zh/guides/basic-features/debug/mock.md): Modern.js 提供了快速生成 Mock 数据的功能,能够让前端独立自主开发,不被后端接口阻塞。
- [本地代理](/zh/guides/basic-features/debug/proxy.md): Modern.js 在 dev.server.proxy 中提供了配置开发环境代理的方式。 例如,将本地开发接口代理到其他地址:
- [使用 Rsdoctor](/zh/guides/basic-features/debug/rsdoctor.md): Rsdoctor 是一个 Rspack 构建分析工具。在 Modern.js 中,我们推荐使用 Rsdoctor 来对构建过程与构建产物进行诊断和分析。
- [使用 Storybook](/zh/guides/basic-features/debug/using-storybook.md): Storybook 是一个专门用于组件调试的工具,它围绕着组件开发提供了: 丰富多样的调试能力可与一些测试工具结合使用可重复使用的文档内容可分享能力工作流程自动化
- [Rstest](/zh/guides/basic-features/testing/rstest.md): Rstest 是由 Rspack 团队开发的测试框架,基于 Rspack 构建,具备很快的测试执行速度。 本指南介绍如何在 Modern.js 中集成 Rstest,并用于 web app 测试。
- [Playwright](/zh/guides/basic-features/testing/playwright.md): Playwright 是一个测试框架,它允许你使用单一的 API,自动的在 Chromium、Firefox 和 WebKit 环境中运行测试用例,你可以使用它来编写 E2E 测试。 在 Modern.js 中使用 Playwright 需要先安装依赖,可以执行以下命令: 上述命令会自动安装 Playwright 依赖,并通过一系列提示帮助你在项目中安装和配置,包括添加一个 playwright.config.ts 文件。 按照默认配置创建后,可以在项目中看到以下文件: 这是默认的测试文件,现在创建一些新的页面,并测试它们。
- [路径别名](/zh/guides/basic-features/alias.md): 路径别名(alias)允许开发者为模块定义别名,以便于在代码中更方便的引用它们。当你想要使用一个简短、易于记忆的名称来代替冗长复杂的路径时,这将非常有用。 例如,假如你在项目中经常引用 src/common/request.ts 模块,你可以为它定义一个别名 @request,然后在代码中通过 `` 来引用它,而不需要每次都写出完整的相对路径。同时,这也允许你将模块移动到不同的位置,而不需要更新代码中的所有 import 语法。 在 Modern.js 中,你有两种方式可以设置路径别名: 通过 tsconfig.json 中的 paths 配置。通过 source.alias 配置。
- [环境变量](/zh/guides/basic-features/env-vars.md): Modern.js 提供了对环境变量的支持,包含内置的环境变量和自定义的环境变量。
- [构建产物目录](/zh/guides/basic-features/output-files.md): 本章节主要介绍构建产物的目录结构,以及如何控制不同类型产物的输出目录。
- [部署应用](/zh/guides/basic-features/deploy.md): 目前,Modern.js 提供了两种部署方式: 你可以将应用自行托管在包含 Node.js 环境的容器中,这为应用提供了部署的灵活性。你也可以通过平台部署应用,目前 Modern.js 官方支持了 Netlify, Vercel 和 Github pages 平台。
- [BFF](/zh/guides/advanced-features/bff.md): BFF(Backends for Frontends)是一种架构模式,主要用于解决前后端协作中的数据聚合问题。在 BFF 架构下,前端应用程序不直接与后端服务通信,而是通过一个专门为前端定制的BFF中间层与后端服务交互。 它的适用场景包括: 根据自身业务需求,对更底层 API 的聚合、映射、裁剪、代理。对一些特定场景的数据进行缓存,提高性能,进而提升用户体验。根据已有接口快速开发新产品。与第三方系统对接,例如登陆鉴权。 Modern.js 官方支持了 BFF,并提供了一体化 BFF 方案来进一步强化 BFF 能力,主要包括以下能力: 快速开发调试上线,在同一项目中运行、构建、部署 BFF 代码。极简的纯函数调用,在前端直接 import BFF 函数,调用时能自动转换成 HTTP 请求。无私有协议,遵循 RESTful API 规范,所有 BFF 接口都是标准化的。完善的 TypeScript 支持。满足用户使用偏好,支持多框架扩展写法。
- [基础用法](/zh/guides/advanced-features/bff/function.md): 在 Modern.js 应用中,开发者可以在 api/lambda 目录下定义接口文件,并导出接口函数。在前端代码中,可以用文件引用的方式,直接调用这些接口函数,发起接口请求。 这种调用方式我们称为一体化调用,开发者无需编写前后端胶水层代码,并天然地保证前后端类型安全。
- [运行时框架](/zh/guides/advanced-features/bff/frameworks.md): Modern.js 以 Hono.js 作为 BFF 和 Server 运行时框架,因此可以基于 Hono.js 生态扩展 BFF Server。 获取请求上下文 在 BFF 函数中,有时需要获取请求上下文,来处理更多逻辑。此时,你可以通过 useHonoContext 来获取: 获取 Cookie 在 BFF 函数中获取 Cookie 时,需要通过 useHonoContext 获取请求上下文,然后使用 c.req.header('cookie') 获取 Cookie 字符串并手动解析: 定义 BFF 函数 使用 Hono 作为运行时框架时,可以通过 Api 函数 定义接口: 使用中间件 Hono 支持丰富的中间件生态,可以在 BFF 函数中使用中间件: 更多 Hono 文档 更多关于 Hono 的详细信息可查看 Hono 官方文档。
- [创建可扩展的 BFF 函数](/zh/guides/advanced-features/bff/operators.md): 上一小节展示了如何在文件中导出一个简单的 BFF 函数。在更复杂的场景下,每个 BFF 函数可能需要做独立的类型校验,前置逻辑等。 因此,Modern.js 暴露了 Api,支持通过该 API 来创建 BFF 函数,通过这种方式创建的 BFF 函数能方便的进行功能拓展。
- [扩展 BFF Server](/zh/guides/advanced-features/bff/extend-server.md): 部分应用中,开发者可能希望对所有 BFF 函数做统一的处理,例如鉴权、日志、数据处理等。 Modern.js 支持用户通过 Middleware 的方式来自由扩展 BFF Server。
- [扩展一体化调用 SDK](/zh/guides/advanced-features/bff/sdk.md): BFF 函数的一体化调用在 CSR 和 SSR 是同构的。Modern.js 封装的请求 SDK,在浏览器端依赖了 Fetch API,在服务端依赖了 node-fetch。但在实际业务场景下,有时需要对请求或响应做一些额外的处理,例如: 在请求头中写入鉴权信息对响应的数据或错误进行统一的处理特定平台无法使用浏览器的原生 fetch 函数,需要使用其他方式发送请求 针对上述的场景,Modern.js 提供了 configure 函数,开放了一系列扩展能力,可以用它配置 ssr 透传请求头,添加拦截器,自定义请求 SDK。
- [文件上传](/zh/guides/advanced-features/bff/upload.md): BFF 搭配运行时框架提供了文件上传能力,支持一体化调用及纯函数手动调用。 BFF 函数 首先创建 api/lambda/upload.ts 文件: 一体化调用 接着在 src/routes/upload/page.tsx 中直接引入函数并调用: 手动上传 可以基于 fetch API 手动上传文件,需要在调用 fetch 时,将 body 设置为 FormData 类型并提交 post 请求。
- [跨项目调用](/zh/guides/advanced-features/bff/cross-project.md): 基于 BFF 架构,Modern.js 提供了跨项目调用的能力,即在一个项目中创建的 BFF 函数可以被其他项目进行一体化调用,实现项目间的函数共享和功能复用。 跨项目调用分为 BFF 的生产端和消费端。生产端负责创建和提供 BFF 服务、生成一体化调用 SDK,而消费端通过调用 SDK 发起接口请求。
- [代码分割](/zh/guides/advanced-features/page-performance/code-split.md): 代码分割(code splitting)是优化前端资源加载的一种常用手段,本文将介绍 Modern.js 支持的三种代码分割方式: 动态 importReact.lazyloadable
- [静态资源内联](/zh/guides/advanced-features/page-performance/inline-assets.md): 静态资源内联是一种优化网页性能的方法,它指的是将静态资源直接内联到 HTML 或 JS 文件中,而不是使用外部文件引用的方式。这样做的好处是减少了浏览器发起的请求数,从而提高页面的加载速度。 不过,静态资源内联也有一些缺点,比如增加了单个文件的体积,可能会导致加载变慢。所以在实际应用中,需要根据具体情况来决定是否使用静态资源内联。 Modern.js 默认会自动内联体积小于 10KB 的静态资源,但有时候你可能需要手动控制某些特殊资源,让其强制内联或者强制不内联,这篇文档阐述了如何进行精确地控制静态资源内联行为。
- [产物体积优化](/zh/guides/advanced-features/page-performance/optimize-bundle.md): 产物体积的优化在生产环境中是非常重要的,因为它直接影响到了线上的用户体验。在这篇文档中,我们将介绍在 Modern.js 中一些常见的产物体积优化方式。
- [React Compiler](/zh/guides/advanced-features/page-performance/react-compiler.md): React Compiler 是 React 官方提供的构建期编译器,通过自动记忆化(memoization)减少不必要的重渲染,无需手动编写 useMemo、useCallback 和 React.memo。 在开始使用 React Compiler 之前,建议阅读 React Compiler 文档,以了解它的功能、当前状态和使用方法。
- [提升构建性能](/zh/guides/advanced-features/build-performance.md): Modern.js 默认对构建性能进行了充分优化,但是随着业务场景变复杂、项目代码量变大,你可能会遇到一些构建性能的问题。 本文档提供了一些可选的提速策略,开发者可以根据实际场景选取其中的部分策略,从而进一步提升构建速度。
- [浏览器兼容性](/zh/guides/advanced-features/compatibility.md)
- [配置底层工具](/zh/guides/advanced-features/low-level.md)
- [源码构建模式](/zh/guides/advanced-features/source-build.md): 源码构建模式用于 monorepo 开发场景,它允许开发者直接引用 monorepo 中其他子项目的源码进行开发。
- [Monitors](/zh/guides/advanced-features/server-monitor/monitors.md): Modern.js 是一个全栈框架,它可以同时支持客户端和服务端的开发。当 Modern.js 在服务端渲染页面时,框架会在运行时插入更多日志与指标,帮助开发者在线上运维时定位问题。 但服务端代码运行在 Node.js 环境中,开发者无法直接通过浏览器控制台来排查问题,而不同的项目可能使用不同的日志库,或是将数据上报到不同的平台。框架无法覆盖所有的场景,因此需要有统一的方式,允许开发者自行管理所有的内置日志与指标。 Monitors 是 Modern.js 提供的帮助开发者监控应用程序的运行情况的模块。它包含注册 Monitor 和分发监控事件两部分能力。当开发者中调用 Monitors 的某个 API 时,框架会对应的监控事件分发到所有注册的 Monitor 中。
- [日志事件](/zh/guides/advanced-features/server-monitor/logger.md): 日志事件是由 Modern.js 分发的,类型为 log 的事件。
- [指标事件](/zh/guides/advanced-features/server-monitor/metrics.md): 指标事件是由 Monitors 分发,类型为 timing 或 counter 的事件。
- [国际化](/zh/guides/advanced-features/international.md): @modern-js/plugin-i18n 是 Modern.js 的国际化插件,基于 i18next 和 react-i18next 构建。 插件本身:负责与 Modern.js 框架的集成,如 SSR 语言传递、路由前缀处理等i18next:核心翻译能力,如 t() 函数、插值、复数、命名空间。react-i18next:React 组件和 Hook,如 useTranslation,实现与 React 生命周期的结合。
- [快速开始](/zh/guides/advanced-features/international/quick-start.md): 本指南将帮助你快速在 Modern.js 项目中集成国际化功能。
- [配置说明](/zh/guides/advanced-features/international/configuration.md): 插件配置分为两个文件,各有职责:
- [语言检测](/zh/guides/advanced-features/international/locale-detection.md): 语言检测指的是在用户没有手动选择语言的情况下,自动推断应该使用哪种语言。插件支持从 URL 路径、Cookie、请求头、浏览器设置等多个来源检测,可以组合使用。
- [资源加载](/zh/guides/advanced-features/international/resource-loading.md): 翻译文件的加载方式取决于你的翻译资源放在哪里:
- [路由集成](/zh/guides/advanced-features/international/routing.md)
- [API 参考](/zh/guides/advanced-features/international/api.md)
- [高级用法](/zh/guides/advanced-features/international/advanced.md)
- [最佳实践](/zh/guides/advanced-features/international/best-practices.md)
- [自定义 Web Server](/zh/guides/advanced-features/web-server.md): Modern.js 将大部分项目需要的服务端能力都进行了封装,通常项目无需进行服务端开发。但在有些开发场景下,例如用户鉴权、请求预处理、添加页面渲染骨架等,项目仍需要对服务端进行定制。 要在 Modern.js 项目中使用自定义 Web Server,请按照以下步骤操作: 安装 @modern-js/server-runtime 依赖 如果项目尚未安装 @modern-js/server-runtime 依赖,请先安装: 创建 server 目录和配置文件 在项目根目录下创建 server/modern.server.ts 文件: 创建文件后,可以在这个文件中编写自定义逻辑。 你可以将 server 目录包含在 tsconfig.json 中
- [简介](/zh/guides/topic-detail/module-federation/introduce.md): 模块联邦(Module Federation)是一种 JavaScript 应用分治的架构模式,它允许你在多个 JavaScript 应用之间共享代码和资源。 在这种分治的模式下,可以帮助你提升应用程序的性能,增强代码可维护性等。
- [开始使用](/zh/guides/topic-detail/module-federation/usage.md): 在 Modern.js 中使用 Module Federation 我们推荐使用官方插件 @module-federation/modern-js-v3。 本章节将会介绍如何通过官方插件搭含生产者应用与消费者应用,我们首先根据 Modern.js 快速上手 创建两个应用。
- [应用级别模块](/zh/guides/topic-detail/module-federation/application.md): Modern.js 提供了运行时 API,支持快速从应用中导出应用级别的 Module Federation 模块。 我们以 使用模块联邦 创建的应用为例,进一步说明如何导入应用级别模块。
- [服务端渲染](/zh/guides/topic-detail/module-federation/ssr.md): @module-federation/modern-js-v3 提供了非常强大的能力,开发者可以非常方便的在 Modern.js 应用中,组合使用 Module Federation 和服务端渲染(SSR)的能力。
- [部署](/zh/guides/topic-detail/module-federation/deploy.md): 通常情况下,部署 Module Federation 应用,需要注意两点: 保证消费者配置文件中的远程模块地址无误,消费者能够正确访问到生产者的 manifest 文件。保证生产者 manifest 文件中各个资源能被正确访问到。 我们推荐使用 Modern.js 的 Node 服务来部署 Module Federation 应用,以获得开箱即用的体验。
- [集成国际化能力](/zh/guides/topic-detail/module-federation/i18n.md): Modern.js 提供了 @modern-js/plugin-i18n 插件来支持国际化能力。当使用 Module Federation 时,需要针对不同的场景(组件或应用)提供相应的 i18n 集成方案。
- [依赖安装问题](/zh/guides/troubleshooting/dependencies.md): 如何查看项目里某个依赖实际安装的版本? 可以使用包管理器自带的 ls 命令来查看项目里依赖的版本。 下面是一些基本的示例,详细用法请查看各个包管理器的文档。 npm / yarn 对于使用 npm 或 yarn 的项目,可以使用 npm ls 命令。 比如执行 npm ls @modern-js/plugin,可以看到如下结果: pnpm 对于使用 pnpm 的项目,可以使用 pnpm ls 命令。 比如执行 pnpm ls @modern-js/plugin --depth Infinity,可以看到如下结果: 安装依赖时提示 The engine "node" is incompatible? 安装依赖时如果出现以下报错提示,说明当前环境使用的 Node.js 版本过低,需要升级 Node.js 到更高版本。 Modern.js 要求 Node.js 版本 >= 20.19.5,我们强烈推荐使用最新的 LTS 版本(如 Node.js 22 LTS)以获得最佳体验。 如果当前环境的 Node.js 版本低于上述要求的版本,则可以使用 nvm 或 fnm 等工具进行版本切换。 下面是使用 nvm 的示例: 在本地开发环境推荐使用 fnm,它的用法与 nvm 相似,但拥有比 nvm 更好的性能。 升级依赖后出现 ReactNode 类型错误? 升级项目的依赖后,如果出现以下类型报错,说明项目中安装了错误的 @types/react 版本。 出现这个问题的原因是 React 18/19 与 React 16/17 中的 ReactNode 类型定义不同,如果项目中出现多个不同 @types/react 版本,就会出现 ReactNode 类型冲突,导致以上报错。 解决方法为将项目中的 @types/react 和 @types/react-dom 锁定在统一的版本上,比如 v19。 关于锁定依赖版本的方法,请参考 锁定子依赖。 执行 pnpm install 之后,控制台出现 peer dependencies 相关 warning? 出现该警告的原因是,某些三方 npm 包声明的 peer dependencies 版本范围与 Modern.js 中安装的版本范围不一致。 绝大多数情况下,peer dependencies 的警告不会影响项目运行,不需要额外进行处理,请忽略相关 warning。 Modern.js 框架最低支持的 React 版本是多少? Modern.js 框架要求使用的 React 版本为 >= 18.0.0。 如果使用 Modern.js 的 runtime 能力(包括 SSR、Streaming SSR、数据加载、路由等),必须使用 React 18 或更高版本。React 16 和 React 17 不再支持。如果仅使用 Modern.js 的构建能力(不使用 runtime),理论上可以使用 React 16 或 React 17,但强烈建议升级到 React 18 以上版本以获得最佳体验和完整功能支持。 Modern.js 配置出现类型错误? 当你在使用 Modern.js 框架时配置文件出现以上报错,可能是由于 Modern.js 相关包的版本号未统一导致。需要手动将所有 @modern-js/** 包的版本统一更新到相同版本。 在 monorepo 中由于不同子项目所用的 Modern.js 框架版本不一致也可能出现以上问题。 关于如何统一升级依赖版本,请参考版本升级文档。
- [命令行问题](/zh/guides/troubleshooting/cli.md): 使用 pnpm 时无法正确传递命令行参数? 在使用 pnpm 调用 package.json 中的命令时,需要注意参数传递的方式: 如果需要传递参数至 pnpm,需要将参数放到命令前。 例如使用 pnpm --filter 参数执行 prepare 命令: 如果需要传递参数至命令,需要将参数放到命令后。 例如,在如下 package.json 配置中: 执行 command 命令时携带参数方式为:
- [构建相关问题](/zh/guides/troubleshooting/builder.md): 如果你遇到了构建相关的问题,可以参考当前文档进行排查。 Rsbuild FAQ Modern.js 内部基于 Rsbuild 封装了自身的构建工具,因此你可以直接参考 Rsbuild 的 FAQ 文档: Rsbuild - 功能类问题Rsbuild - 异常类问题Rsbuild - 热更新问题 如何查看最终生成的 Rspack 配置? Modern.js 提供 inspect 命令 用于查看项目最终生成的 Modern.js 配置以及 Rspack 配置。 在 Monorepo 中引用其他模块,代码没有被正确编译? 出于编译性能的考虑,默认情况下,Modern.js 不会编译 node_modules 下的文件,也不会编译当前工程目录外部的文件。 因此,当你引用其他子项目的源代码时,可能会遇到类似 You may need an additional loader to handle the result of these loaders. 的报错。 这个问题有以下解决方法: 你可以开启源码构建模式来编译 monorepo 中的其他子项目,参考「源码构建模式」。你可以添加 source.include 配置项,指定需要额外进行编译的目录或模块,参考 source.include 用法介绍。你可以预先构建需要引用的子项目,生成对应的构建产物,并在当前项目引用构建产物,而不是引用源代码。 打开页面后报错,提示 exports is not defined? 如果编译正常,但是打开页面后出现 exports is not defined 报错,通常是因为在项目中使用 Babel 编译了一个 CommonJS 模块,导致 Babel 出现异常。 在正常情况下,Modern.js 是不会使用 Babel 来编译 CommonJS 模块的。如果项目中使用了 source.include 配置项,则可能会把一些 CommonJS 模块加入到 Babel 编译中。 该问题有两种解决方法: 避免将 CommonJS 模块加入到 Babel 编译中。将 Babel 的 sourceType 配置项设置为 unambiguous。将 sourceType 设置为 unambiguous 可能会产生一些其他影响,请参考 Babel 官方文档。 编译时报错 "Error: ES Modules may not assign module.exports or exports.*, Use ESM export syntax"? 如果编译时出现以下报错,通常也是因为在项目中使用 Babel 编译了一个 CommonJS 模块,解决方法与上述的 exports is not defined 问题一致。 更多信息请参考 issue:babel#12731。 编译进度条卡死,但终端无 Error 日志? 当编译进度条卡死,但终端无 Error 日志时,通常是因为编译过程中出现了异常。在某些情况下,当 Error 被构建工具或其他模块捕获后,错误日志不会被正确输出。最为常见的场景是 Babel 配置出现异常,抛出 Error 后被构建工具捕获,而构建工具在个别情况下吞掉了 Error。 解决方法: 如果你修改 Babel 配置后出现此问题,建议检查是否有以下错误用法: 配置了一个不存在的 plugin 或 preset,可能是名称拼写错误,或是未正确安装。是否配置了多个 babel-plugin-import,但是没有在数组的第三项声明每一个 babel-plugin-import 的名称。 从 lodash 中引用类型后出现编译报错? 当你的项目中安装了 @types/lodash 包时,你可能会从 lodash 中引用一些类型,比如引用 DebouncedFunc 类型: 上述代码会在编译后产生如下报错: 这个问题的原因是 Modern.js 默认开启了 babel-plugin-lodash 插件来优化 lodash 产物体积,但 Babel 无法区别「值」和「类型」,导致编译后的代码出现异常。 解决方法是使用 TypeScript 的 import type 语法,对 DebouncedFunc 类型进行显式声明: 升级 Modern.js 版本后,检查出新的 TypeScript 类型错误? Modern.js 优化了 Type Checker 的检查范围。在之前的版本中,Type Checker 只输出 src 目录的类型错误,导致其他目录的类型错误无法被正确输出。 在新版本中,Modern.js 的 Type Checker 对齐了原生 tsc 的类型检查范围(即 tsconfig.json 的 include 和 exclude 字段定义的范围),能够完整输出项目中的类型错误。 如果你希望保持之前的行为,只输出 src 目录的类型错误,可以添加以下配置:
- [热更新问题](/zh/guides/troubleshooting/hmr.md): 热更新不生效,如何排查? 热更新不生效有很多种可能的原因,在这篇文档中会介绍大部分常见的原因,你可以参照以下内容进行排查。 在开始排查之前,请简单了解一下热更新的原理: 了解完热更新的原理后,你可以按照以下步骤来进行基本的排查: 1. 检查 Web Socket 连接 打开浏览器的控制台,查看是否有 [HMR] connected. 日志。 如果有,说明 Web Socket 连接正常,请继续检查后续步骤。如果没有,请打开 Chrome 的 Network 面板,查看 ws://[host]:[port]/webpack-hmr 的请求状态,若请求异常,说明热更新失败的原因是 Web Socket 请求没有建立成功。 Web Socket 请求没有建立成功的原因可能有很多种,例如开启了网络代理,导致 Web Socket 请求没有正确发送到开发服务器。你可以检查 Web Socket 请求的地址是否为你的开发服务器地址,如果不是,则可以通过 tools.devServer.client 来配置 Web Socket 请求的地址。 2. 检查 hot-update 请求 当你修改一个模块的代码,并触发重新编译后,浏览器会向开发服务器发送若干个 hot-update.json 和 hot-update.js 请求,用于获取更新后的代码。 你可以尝试修改一个模块并检查 hot-update.xxx 请求的内容,如果请求的内容是最新的代码,说明热更新的请求正常。 如果请求的内容错误,大概率也是由于开启了网络代理,请检查 hot-update.xxx 请求的地址是否为你的开发服务器地址,如果不是,则需要调整代理规则,将 hot-update.xxx 请求代理到开发服务器地址。 3. 检查其他原因 如果以上两个步骤都没有问题,那么可能是其他原因导致的热更新失败,比如没有符合 React 对热更新的要求,你可以参考下列的问题进行排查。 打包时 external React 后,热更新不生效? 为了保证热更新生效,我们需要使用 React 和 ReactDOM 的开发环境产物。 当你将 React 通过 externals 排除后,通常会通过 CDN 等方式注入 React 的生产环境产物,所以热更新会不生效。 为了解决该问题,你需要引用 React 的开发环境产物,或者在开发环境下不配置 externals。 如果你不确定当前使用的 React 产物类型,可以参考:React 官方文档 - Use the Production Build 开发环境设置文件名的 hash 后,热更新不生效? 通常来说,我们只会在生产环境下设置文件名的 hash 值(即 process.env.NODE_ENV === 'production' 时)。 如果你在开发环境下设置了文件名的 hash,那么可能会导致热更新不生效(尤其是 CSS 文件)。这是因为每次文件内容变化时,都会引起 hash 变化,导致 mini-css-extract-plugin 等工具无法读取到最新的文件内容。 正确用法: 错误用法: React 组件的热更新无法生效? Modern.js 使用 React 官方的 Fast Refresh 能力来进行组件热更新。 如果出现 React 组件的热更新无法生效的问题,或者是热更新后 React 组件的 state 丢失,这通常是因为你的 React 组件使用了匿名函数。在 React Fast Refresh 的官方实践中,要求组件不能为匿名函数,否则热更新后无法保留 React 组件的 state。 以下是一些错误用法的例子: 正确用法是给每个组件函数声明一个名称: 开启 https 后,热更新不生效? 当开启 https 时,由于证书的问题,可能会出现 HMR 连接失败的情况,此时打开控制台,会出现 HMR connect failed 的报错。 此问题的解决方法为:点击 Chrome 浏览器问题页面的「高级」->「继续前往 xxx(不安全)」。 Tips: 当通过 Localhost 访问页面时,「您的连接不是私密连接」字样可能不会出现,可访问 Network 域名进行处理。
- [概述](/zh/guides/upgrade/overview.md): 本文档将帮助您从 Modern.js 2.0 升级到 Modern.js 3.0。
- [配置变更](/zh/guides/upgrade/config.md): 本篇文档主要介绍从 Modern.js 2.0 升级到 3.0 时,配置项层面的不兼容变更以及推荐的迁移方式。
- [入口变更](/zh/guides/upgrade/entry.md): 本章节介绍 Modern.js 从 2.0 升级到 3.0 时,页面入口相关的变更内容。
- [自定义 Web Server 变化](/zh/guides/upgrade/web-server.md): 本章节覆盖两类旧版自定义 Server API 的升级 unstableMiddlewareHook 这两种写法在旧版中互斥,迁移时请根据项目实际使用的能力选择对应路径。
- [Tailwind 插件变更](/zh/guides/upgrade/tailwindcss.md): Modern.js 3.0 推荐通过 Rsbuild 原生方式接入 Tailwind CSS,不再依赖 @modern-js/plugin-tailwindcss 插件,从而充分利用 Rsbuild 提供的更灵活的配置能力和更优的构建体验。
- [其他重要变更](/zh/guides/upgrade/other.md): 本篇文档介绍从 Modern.js 2.0 升级到 3.0 时,其他重要的不兼容变更以及相关的迁移说明。
## 配置
- [配置使用](/zh/configure/app/usage.md): Modern.js 中有三种配置,分别是编译时配置、运行时配置和服务端运行时配置。 编译时配置可以在两个位置进行配置: 根路径下的 modern.config.(ts|js|mjs) 文件package.json 文件 运行时配置可以在 src/modern.runtime.(ts|js|mjs) 文件中配置。 服务端运行时配置可以在 server/modern.server.(ts|js|mjs) 中进行配置。
- [assetPrefix](/zh/configure/app/dev/asset-prefix.md): 类型: boolean | string | 'auto'默认值: '/' 此配置项用于设置 开发模式 下的静态资源 URL 前缀。
- [beforeStartUrl](/zh/configure/app/dev/before-start-url.md): 类型: () => Promise | void默认值: undefined dev.beforeStartUrl 用于在打开 startUrl 前执行一段回调函数,该配置项需要与 dev.startUrl 一同使用。
- [client](/zh/configure/app/dev/client.md): 类型: 默认值: 配置 Modern.js 在开发过程中注入的 client 代码,可以用于设置热更新对应的 WebSocket URL。
- [hmr](/zh/configure/app/dev/hmr.md): 类型: boolean默认值: true 是否开启 Hot Module Replacement 热更新能力。
- [host](/zh/configure/app/dev/host.md): 类型: string默认值: 0.0.0.0 指定 dev server 启动时监听的 host。 默认情况下,dev server 会监听 0.0.0.0,这代表监听所有的网络接口,包括 localhost 和公网地址。 如果你希望 dev server 只监听 localhost,可以设置为:
- [https](/zh/configure/app/dev/https.md): 类型: boolean | { key: string; cert: string }默认值: false 配置该选项后,可以开启 Dev Server 对 HTTPS 的支持,同时会禁用 HTTP 服务器。 开启前: 开启后: 自动生成证书 你可以直接将 https 设置为 true,Modern.js 会基于 devcert 来自动生成 Dev Server 所需的 HTTPS 证书。 使用这种方式时,你需要在当前项目中手动安装 devcert 依赖: 然后配置 dev.https 为 true 即可: 该方式有一定局限性,由于 devcert 目前不支持 IP addresses,因此访问 Network 域名时,会遇到「您的连接不是私密连接」的问题。 此问题的解决方法为:点击 Chrome 浏览器问题页面的「高级」->「继续前往 192.168.0.1(不安全)」。 手动设置证书 你也可以在 dev.https 选项中手动传入 HTTPS 服务器所需要的证书和对应的私钥,这个参数将直接传递给 Node.js 中 https 模块的 createServer。 具体可以参考 https.createServer。 清理证书缓存 devcert 默认会将生成的证书缓存在 ~/Library/Application\ Support/devcert ,你可以按需清理。
- [lazyCompilation](/zh/configure/app/dev/lazy-compilation.md): 类型: 默认值: 取决于应用的渲染方式:纯 CSR 与流式 SSR 应用:{ imports: true, entries: false },即对动态导入按需编译;使用 string SSR(包括 server.ssrByEntries 中任一入口为 string SSR)、RSC 或 SSG 的应用:false。 用于开启 lazy compilation(即按需编译),基于 Rspack 的 lazy compilation 特性实现。 该配置仅在开发环境(dev server)下生效,不影响生产构建产物。流式 SSR 应用开启时,路由组件仍会提前编译,以保证首屏 JS/CSS 注入正确。 显式配置的 dev.lazyCompilation 始终优先于默认值,如需关闭可配置:
- [liveReload](/zh/configure/app/dev/live-reload.md): 类型: boolean默认值: true 是否在源文件变更时自动刷新页面。
- [mockDir](/zh/configure/app/dev/mock-dir.md): 类型: string默认值: './config/mock' 设置 Mock API 入口文件所在的目录。相对路径基于应用目录解析,同时也支持绝对路径。 开发环境下,Modern.js 会加载该目录中的 index.ts 或 index.js。 例如,将 Mock API 入口移动到 mocks/index.ts: 在 Monorepo 中,也可以让多个应用指向一个共享的 Mock 目录:
- [progressBar](/zh/configure/app/dev/progress-bar.md): 类型: 默认值: true 是否在编译过程中展示进度条。
- [server](/zh/configure/app/dev/server.md): 类型: Object默认值: {} 通过 dev.server 可以修改开发环境服务器的配置。 compress 类型: boolean默认值: true 是否对静态资源启用 gzip 压缩。 如果你需要禁用 gzip 压缩,可以将 compress 设置为 false: 更多详细信息请参考 Rsbuild - server.compress 文档。 headers 类型: Record默认值: undefined 设置自定义响应头。 更多详细信息请参考 Rsbuild - server.headers 文档。 historyApiFallback 类型: boolean | ConnectHistoryApiFallbackOptions默认值: false 在需要对一些 404 响应或其他请求提供替代页面的场景,可通过 dev.server.historyApiFallback 进行设置: 更多配置选项请参考 Rsbuild - server.historyApiFallback 文档。 watch 类型: boolean默认值: true 是否监听 mock/、server/、api/ 等目录的文件变化。 更多详细信息请参考 Rsbuild - dev.watchFiles 文档。 cors 类型: boolean | import('cors').CorsOptions 为开发服务器配置 CORS(跨域资源共享)。 Modern.js 中 cors 的默认配置遵循 Rsbuild 的默认值: 更多配置选项和详细用法请参考 Rsbuild - server.cors 文档。 proxy 类型: ProxyOptions[] | Record默认值: undefined 为开发服务器配置代理规则,把请求转发到指定服务。
- [setupMiddlewares](/zh/configure/app/dev/setup-middlewares.md): 类型: 默认值: undefined 提供执行自定义函数和应用自定义中间件的能力。
- [startUrl](/zh/configure/app/dev/start-url.md): 类型: boolean | string | string[] | undefined默认值: undefined dev.startUrl 用于设置 Dev Server 启动时自动在浏览器中打开的页面 URL。 默认情况下,Dev Server 启动时不会打开任何页面。 你可以设置为如下的值: 端口号占位符 由于端口号可能会发生变动,你可以使用 占位符来指代当前端口号,Modern.js 会自动将占位符替换为实际监听的端口号。 打开指定浏览器 在 MacOS 上,通过设置环境变量 BROWSER,你可以指定 Dev Server 在启动时打开的浏览器,支持如下的值: Google Chrome CanaryGoogle Chrome DevGoogle Chrome BetaGoogle ChromeMicrosoft EdgeBrave BrowserVivaldiChromium 建议设置在.env.local文件中。
- [watchFiles](/zh/configure/app/dev/watch-files.md): 类型: 默认值: undefined 监听指定文件和目录的变化。当文件发生变化时,可以触发页面的重新加载,或者触发 dev server 重新启动。
- [writeToDisk](/zh/configure/app/dev/write-to-disk.md): 类型: boolean | ((filename: string) => boolean)默认值: (file: string) => !file.includes('.hot-update.') 用于控制是否将开发环境的构建产物写入到磁盘上。
- [crossProject](/zh/configure/app/bff/cross-project.md): 类型: boolean默认值: false 该配置用于启用 BFF 跨项目调用功能。启用后,可以将当前项目作为 BFF 生产端,生成可被其他项目直接调用的 SDK。 有关 BFF 跨项目调用的详细配置和使用方法,请参考 BFF 跨项目调用指南。
- [prefix](/zh/configure/app/bff/prefix.md): 类型: string默认值: /api 默认情况下,BFF API 目录下的路由访问前缀是 /api, 如下目录结构: api/hello.ts 访问时对应的路由为 localhost:8080/api/hello。 该配置选项可以修改默认的路由前缀: 对应的 api/hello.ts 访问路由为 localhost:8080/api-demo/hello。
- [appIcon](/zh/configure/app/html/app-icon.md): 类型: 默认值: undefined 设置 Web 应用的图标,用于在添加到移动设备的主屏幕时显示: 生成 web app manifest 文件和其中的 icons 字段。生成 HTML 文件中的 apple-touch-icon 标签和 manifest 标签。
- [crossorigin](/zh/configure/app/html/crossorigin.md): 类型: boolean | 'anonymous' | 'use-credentials'默认值: false 用于设置