@bleedingdev/modern-js-main-doc 3.2.0-ultramodern.98 → 3.4.0-ultramodern.0
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/apis/app/commands.mdx +59 -69
- package/docs/en/community/blog/v2-release-note.mdx +5 -5
- package/docs/en/community/blog/v3-release-note.mdx +1 -1
- package/docs/en/community/releases.mdx +1 -5
- package/docs/en/components/build-output.mdx +1 -1
- package/docs/en/components/debug-app.mdx +1 -1
- package/docs/en/components/deploy-command.mdx +3 -3
- package/docs/en/components/init-app.mdx +23 -51
- package/docs/en/components/prerequisites.mdx +1 -1
- package/docs/en/components/serve-command.mdx +3 -3
- package/docs/en/configure/app/bff/effect.mdx +27 -3
- package/docs/en/configure/app/performance/rsdoctor.mdx +7 -4
- package/docs/en/configure/app/tools/ts-checker.mdx +30 -2
- package/docs/en/configure/app/usage.mdx +6 -6
- package/docs/en/guides/advanced-features/bff/data-platform.mdx +3 -1
- package/docs/en/guides/advanced-features/bff/frameworks.mdx +3 -1
- package/docs/en/guides/advanced-features/international/api.mdx +1 -1
- package/docs/en/guides/advanced-features/international/configuration.mdx +1 -1
- package/docs/en/guides/advanced-features/international/locale-detection.mdx +1 -1
- package/docs/en/guides/advanced-features/international/routing.mdx +5 -3
- package/docs/en/guides/advanced-features/web-server.mdx +12 -0
- package/docs/en/guides/basic-features/debug/rsdoctor.mdx +2 -3
- package/docs/en/guides/basic-features/debug/using-storybook.mdx +1 -1
- package/docs/en/guides/basic-features/deploy.mdx +14 -14
- package/docs/en/guides/basic-features/env-vars.mdx +2 -2
- package/docs/en/guides/basic-features/render/_meta.json +1 -10
- package/docs/en/guides/basic-features/render/overview.mdx +0 -1
- package/docs/en/guides/basic-features/render/rsc.mdx +0 -1
- package/docs/en/guides/basic-features/routes/config-routes.mdx +2 -2
- package/docs/en/guides/basic-features/routes/routes.mdx +25 -10
- package/docs/en/guides/basic-features/testing/rstest.mdx +29 -0
- package/docs/en/guides/concept/server.mdx +2 -2
- package/docs/en/guides/get-started/quick-start.mdx +1 -1
- package/docs/en/guides/get-started/ultramodern.mdx +135 -26
- package/docs/en/guides/topic-detail/module-federation/application.mdx +1 -1
- package/docs/en/guides/topic-detail/module-federation/deploy.mdx +2 -2
- package/docs/en/guides/topic-detail/module-federation/usage.mdx +5 -5
- package/docs/en/guides/troubleshooting/builder.mdx +1 -1
- package/docs/en/guides/upgrade/config.mdx +1 -2
- package/docs/en/guides/upgrade/other.mdx +4 -4
- package/docs/zh/apis/app/commands.mdx +56 -66
- package/docs/zh/community/blog/v2-release-note.mdx +5 -5
- package/docs/zh/community/blog/v3-release-note.mdx +1 -1
- package/docs/zh/community/releases.mdx +1 -5
- package/docs/zh/components/build-output.mdx +1 -1
- package/docs/zh/components/debug-app.mdx +1 -1
- package/docs/zh/components/deploy-command.mdx +3 -3
- package/docs/zh/components/init-app.mdx +16 -47
- package/docs/zh/components/prerequisites.mdx +1 -1
- package/docs/zh/components/serve-command.mdx +3 -3
- package/docs/zh/configure/app/bff/effect.mdx +26 -2
- package/docs/zh/configure/app/performance/rsdoctor.mdx +7 -4
- package/docs/zh/configure/app/tools/ts-checker.mdx +30 -2
- package/docs/zh/configure/app/usage.mdx +6 -6
- package/docs/zh/guides/advanced-features/bff/data-platform.mdx +3 -1
- package/docs/zh/guides/advanced-features/bff/frameworks.mdx +3 -1
- package/docs/zh/guides/advanced-features/international/api.mdx +1 -1
- package/docs/zh/guides/advanced-features/international/configuration.mdx +1 -1
- package/docs/zh/guides/advanced-features/international/locale-detection.mdx +1 -1
- package/docs/zh/guides/advanced-features/international/routing.mdx +5 -3
- package/docs/zh/guides/advanced-features/web-server.mdx +12 -0
- package/docs/zh/guides/basic-features/debug/rsdoctor.mdx +2 -3
- package/docs/zh/guides/basic-features/debug/using-storybook.mdx +1 -1
- package/docs/zh/guides/basic-features/deploy.mdx +13 -13
- package/docs/zh/guides/basic-features/env-vars.mdx +2 -2
- package/docs/zh/guides/basic-features/render/_meta.json +1 -10
- package/docs/zh/guides/basic-features/render/overview.mdx +0 -1
- package/docs/zh/guides/basic-features/render/rsc.mdx +0 -1
- package/docs/zh/guides/basic-features/routes/config-routes.mdx +2 -2
- package/docs/zh/guides/basic-features/routes/routes.mdx +25 -10
- package/docs/zh/guides/basic-features/testing/rstest.mdx +29 -0
- package/docs/zh/guides/concept/server.mdx +2 -2
- package/docs/zh/guides/get-started/quick-start.mdx +1 -1
- package/docs/zh/guides/get-started/ultramodern.mdx +121 -22
- package/docs/zh/guides/topic-detail/module-federation/application.mdx +1 -1
- package/docs/zh/guides/topic-detail/module-federation/deploy.mdx +2 -2
- package/docs/zh/guides/topic-detail/module-federation/usage.mdx +5 -5
- package/docs/zh/guides/troubleshooting/builder.mdx +1 -1
- package/docs/zh/guides/upgrade/config.mdx +1 -2
- package/docs/zh/guides/upgrade/other.md +4 -4
- package/package.json +17 -14
- package/rspress.config.ts +17 -5
- package/src/components/Footer/index.tsx +3 -3
- package/src/components/Footer/styles.module.scss +1 -1
- package/src/components/Mermaid/style.scss +52 -52
- package/src/components/RandomMemberList/index.module.scss +8 -8
- package/src/components/SecondaryTitle/index.module.css +7 -2
- package/src/components/ShowcaseList/index.module.scss +1 -1
- package/src/components/ShowcaseList/useShowcases.ts +23 -65
- package/src/i18n/enUS.ts +0 -9
- package/src/i18n/zhCN.ts +0 -9
- package/src/pages/index.module.scss +6 -6
- package/src/sandbox/csr-auth/src/routes/page-tsx.txt +1 -1
- package/static/img/logo.svg +7 -0
- package/static/img/social-card.svg +12 -0
- package/builder-doc/docs/en/config/performance/rsdoctor.md +0 -37
- package/builder-doc/docs/zh/config/performance/rsdoctor.md +0 -37
- package/docs/en/guides/basic-features/render/tanstack-rsc.mdx +0 -226
- package/docs/zh/guides/basic-features/render/tanstack-rsc.mdx +0 -226
- package/main-doc/docs/en/guides/get-started/ultramodern.mdx +0 -403
- package/main-doc/docs/zh/guides/get-started/ultramodern.mdx +0 -363
|
@@ -466,7 +466,7 @@ Modern.js 支持通过 `loading.tsx` 文件来解决这个问题,`routes/` 下
|
|
|
466
466
|
|
|
467
467
|
## 预加载
|
|
468
468
|
|
|
469
|
-
大多数切换路由时白屏的情况,都可以通过定义 `<Loading>` 组件来优化体验。Modern.js 也支持在 `<Link>` 组件上定义 `prefetch`
|
|
469
|
+
大多数切换路由时白屏的情况,都可以通过定义 `<Loading>` 组件来优化体验。Modern.js 也支持在 `<Link>` 组件上定义 `prefetch` 和 `preload` 属性,提前对导航进行预热。
|
|
470
470
|
|
|
471
471
|
对于有更高性能要求的应用,预加载可以进一步提升用户体验,减少展示 `<Loading>` 组件的时间:
|
|
472
472
|
|
|
@@ -476,21 +476,36 @@ Modern.js 支持通过 `loading.tsx` 文件来解决这个问题,`routes/` 下
|
|
|
476
476
|
|
|
477
477
|
:::tip
|
|
478
478
|
|
|
479
|
-
|
|
479
|
+
在 SSR 项目中,同源路由会为匹配到且带有可调用 loader 的路由预取 [Data Loader](/guides/basic-features/data/data-fetch) 返回的数据。如果某个路由的 loader 数据不应该在导航前请求,可以将该路由的 `handle.navigationWarmup.data` 设置为 `false`。
|
|
480
480
|
|
|
481
481
|
:::
|
|
482
482
|
|
|
483
|
-
|
|
483
|
+
默认情况下,同源链接会在 `<Link>` 渲染时预取路由模块和匹配到的 loader 数据。当用户开启 Save-Data 或处于慢速网络时,Modern.js 会跳过这些自动预热。
|
|
484
484
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
- `render
|
|
485
|
+
`prefetch` 属性有四个可选值:
|
|
486
|
+
|
|
487
|
+
- `render`,默认值。当 `<Link>` 组件渲染时,就会预热对应的路由模块。
|
|
488
|
+
- `intent`,当用户聚焦、悬停或触摸链接时,会开始预热对应的路由模块。如果意图在预热开始前取消,预热也会取消。
|
|
489
|
+
- `viewport`,当 `<Link>` 组件进入视窗时,会开始预热对应的路由模块。
|
|
490
|
+
- `none`,关闭自动 prefetch。如果没有显式设置 `preload`,也会关闭隐式 preload。
|
|
491
|
+
|
|
492
|
+
`preload` 属性接受同样的时机值,默认跟随 `prefetch` 的时机。显式设置的 `preload` 总是优先生效,`preload={false}` 会关闭 preload 行为。
|
|
493
|
+
|
|
494
|
+
如果要让某个路由关闭 SSR 数据预热:
|
|
495
|
+
|
|
496
|
+
```ts title="routes/page.config.ts"
|
|
497
|
+
export const handle = {
|
|
498
|
+
navigationWarmup: {
|
|
499
|
+
data: false,
|
|
500
|
+
},
|
|
501
|
+
};
|
|
502
|
+
```
|
|
488
503
|
|
|
489
504
|
:::details 值为 render 和不做路由分片的区别
|
|
490
505
|
|
|
491
|
-
- `render`
|
|
492
|
-
- `
|
|
493
|
-
-
|
|
506
|
+
- `render` 可以通过 `<Link>` 组件在组件树中的位置控制路由模块预热时机。
|
|
507
|
+
- `viewport` 可以把模块预热推迟到链接接近可操作时再触发。
|
|
508
|
+
- SSR 数据预取默认开启;当路由的 loader 数据不适合在导航前获取时,使用 `handle.navigationWarmup.data = false` 关闭。
|
|
494
509
|
|
|
495
510
|
:::
|
|
496
511
|
|
|
@@ -516,6 +531,6 @@ Modern.js 提供了按路由框架区分的运行时导出:
|
|
|
516
531
|
|
|
517
532
|
:::note
|
|
518
533
|
|
|
519
|
-
如果应用中必须直接使用 React Router 包的 API,例如部分路由行为被封装在统一的 npm 包中,那应用可以通过设置 [`source.alias`](/configure/app/source/alias),将 `react-router`
|
|
534
|
+
如果应用中必须直接使用 React Router 包的 API,例如部分路由行为被封装在统一的 npm 包中,那应用可以通过设置 [`source.alias`](/configure/app/source/alias),将 `react-router` 指向项目的依赖,避免两个版本的 React Router 同时存在的问题。
|
|
520
535
|
|
|
521
536
|
:::
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
先安装基础依赖:
|
|
10
10
|
|
|
11
|
+
import { Prompt } from '@rspress/core/theme';
|
|
11
12
|
import { PackageManagerTabs } from '@theme';
|
|
12
13
|
|
|
13
14
|
<PackageManagerTabs command="add @rstest/core @modern-js/adapter-rstest -D" />
|
|
@@ -161,3 +162,31 @@ test('Page', () => {
|
|
|
161
162
|
如果你需要测试 `bff` 等 server-side logic,建议直接参考 [Rstest 文档](https://rstest.rs) 中关于 node mode 的说明。
|
|
162
163
|
|
|
163
164
|
Modern.js 主要面向 web app,因此这里重点介绍的是 Web UI 测试,以及更贴近真实运行环境的 browser mode。
|
|
165
|
+
|
|
166
|
+
## 从已有项目迁移
|
|
167
|
+
|
|
168
|
+
如果你的项目已经使用 Jest 或 Vitest,可以参考 Rstest 官方迁移指南:
|
|
169
|
+
|
|
170
|
+
- [从 Jest 迁移到 Rstest](https://rstest.rs/guide/migration/jest)
|
|
171
|
+
- [从 Vitest 迁移到 Rstest](https://rstest.rs/guide/migration/vitest)
|
|
172
|
+
|
|
173
|
+
推荐先安装 `migrate-to-rstest` skill,再复制下面的 Prompt 给编码 Agent;它会在迁移时保留 Modern.js 的 `@modern-js/adapter-rstest` 配置。
|
|
174
|
+
|
|
175
|
+
<Prompt
|
|
176
|
+
title="迁移到 Rstest"
|
|
177
|
+
description="复制这个 Prompt 并发送给你的编码 Agent。"
|
|
178
|
+
prompt={`Migrate this Modern.js project from Jest or Vitest to Rstest.
|
|
179
|
+
|
|
180
|
+
First install and use the migrate-to-rstest skill. If it is not installed, install it with:
|
|
181
|
+
npx skills add rstackjs/agent-skills --skill migrate-to-rstest
|
|
182
|
+
|
|
183
|
+
Follow the migrate-to-rstest skill instructions and the official Rstest migration guides:
|
|
184
|
+
- Jest: https://rstest.rs/guide/migration/jest
|
|
185
|
+
- Vitest: https://rstest.rs/guide/migration/vitest
|
|
186
|
+
|
|
187
|
+
Modern.js-specific requirement:
|
|
188
|
+
- Install and use @modern-js/adapter-rstest together with @rstest/core.
|
|
189
|
+
- Create or update rstest.config.ts to import withModernConfig from @modern-js/adapter-rstest.
|
|
190
|
+
- Reuse the Modern.js app configuration with extends: withModernConfig().
|
|
191
|
+
- Do not replace this with a plain Rstest config unless the project explicitly does not need Modern.js config integration.`}
|
|
192
|
+
/>
|
|
@@ -26,10 +26,10 @@ Modern.js 开发环境和生产环境的 Web 服务器流程是完全同构的
|
|
|
26
26
|
|
|
27
27
|
Modern.js 支持在任何 Node.js 环境运行构建产物。在 CI 环境中,通常情况下已经安装了应用全部的依赖。
|
|
28
28
|
|
|
29
|
-
你可以执行 [`
|
|
29
|
+
你可以执行 [`modern build`](/apis/app/commands#modern-build) 来构建应用,执行 [`modern serve`](/apis/app/commands#modern-serve) 命令来运行 Web 服务器,启动 UltraModern.js 应用。
|
|
30
30
|
|
|
31
31
|
## 在生产环境中运行
|
|
32
32
|
|
|
33
33
|
在部署到生产环境时,产物体积应该尽可能小,而上述在 CI 中运行的方案,会保留原项目的所有产物。因此在生产环境,不推荐通过上述命令运行应用。
|
|
34
34
|
|
|
35
|
-
UltraModern.js 提供了独立的部署方案,当运行 [`
|
|
35
|
+
UltraModern.js 提供了独立的部署方案,当运行 [`modern deploy`](/apis/app/commands#modern-deploy) 命令时,产物中会包含可运行 Web 服务器的入口文件。
|
|
@@ -46,7 +46,7 @@ export default defineConfig({
|
|
|
46
46
|
|
|
47
47
|
在新创建的工程中,默认会安装 `@modern-js/app-tools` npm 包,它是 Modern.js 框架的核心包,主要提供以下能力:
|
|
48
48
|
|
|
49
|
-
- 提供 `
|
|
49
|
+
- 提供 `modern dev`, `modern build` 等常用的 CLI 命令。
|
|
50
50
|
- 集成 Rsbuild,提供构建能力。
|
|
51
51
|
- 集成 Modern.js Server,提供开发和生产服务器相关能力。
|
|
52
52
|
|
|
@@ -30,7 +30,7 @@ UltraModern.js 的增强能力是新 SuperApp 的默认产品面。兼容分支
|
|
|
30
30
|
|
|
31
31
|
| 领域 | Modern.js 3.0 基线 | UltraModern.js 3.0 |
|
|
32
32
|
| --- | --- | --- |
|
|
33
|
-
| 构建诊断能力 | RsDoctor 多为显式开启 |
|
|
33
|
+
| 构建诊断能力 | RsDoctor 多为显式开启 | 新增一等的 `performance.rsdoctor` 配置项(按需开启;早期的默认开启行为与诊断契约产物已回退) |
|
|
34
34
|
| 输出与静态资源回源 | 预压缩策略通常由业务自定义 | 默认开启 `output.precompress`,并按 `Accept-Encoding` 协商 `.br` / `.gz` 回源 |
|
|
35
35
|
| BFF 运行时与契约 | 提供标准 BFF 运行时与客户端生成能力 | 增加 `requestId` 维度隔离、初始化 fail-fast 校验与操作/追踪关联 Header |
|
|
36
36
|
| BFF 运行时选型 | Modern.js 3.0 基线仅提供 Hono 运行时路径(无内建 Effect 运行时) | 将 Effect 设为默认运行时,并采用严格运行时拆分(`effect` -> `api/effect`,`hono` -> `api/lambda`),同时补齐 Effect-Schema-first 契约与 MF failure-injection 覆盖 |
|
|
@@ -40,7 +40,7 @@ UltraModern.js 的增强能力是新 SuperApp 的默认产品面。兼容分支
|
|
|
40
40
|
| 模块准入治理 | 基线无模块认证证据化 gate profile | 新增模块 SDK 契约、边界反模式守卫与发布/模块认证 gate 工作流 |
|
|
41
41
|
| 路由运行时 | 默认运行时路径以 React Router 为中心 | 增加 TanStack Router 运行时/CLI 一等支持(React Router 继续可用) |
|
|
42
42
|
| 脚手架模板 | 默认 create 模板以 React Router 起步路径为中心 | 增加 TanStack-ready 与 Tailwind-ready 的 create 模板 |
|
|
43
|
-
| Starter 预设约束 | 生成应用默认没有 UltraModern 预设 gate 工作流 |
|
|
43
|
+
| Starter 预设约束 | 生成应用默认没有 UltraModern 预设 gate 工作流 | 生成 workspace 会附带 `.github/workflows/ultramodern-workspace-gates.yml`、`pnpm check`、基础本地 gate 与生成契约校验 |
|
|
44
44
|
|
|
45
45
|
## 我们刻意不做的事情
|
|
46
46
|
|
|
@@ -49,38 +49,51 @@ UltraModern.js 的增强能力是新 SuperApp 的默认产品面。兼容分支
|
|
|
49
49
|
- 运行时保持 `effect` 与 `hono` 双模式并存,但不提供隐式回退。
|
|
50
50
|
- 除非稳定性硬需求,否则避免引入破坏性 API 变更。
|
|
51
51
|
|
|
52
|
-
##
|
|
52
|
+
## 迁移指南
|
|
53
53
|
|
|
54
|
-
对于已经在使用 Modern.js 3.0 的团队,迁移路径是“兼容感知”:保留能降低风险的部分,逐步向 MV-first / TanStack-first / Effect-first 默认方向收敛,并把 UltraModern.js 3.0 作为独立框架采用。
|
|
54
|
+
对于已经在使用 Modern.js 3.0 或旧版 BleedingDev UltraModern scaffold 的团队,迁移路径是“兼容感知”:保留能降低风险的部分,逐步向 MV-first / TanStack-first / Effect-first 默认方向收敛,并把 UltraModern.js 3.0 作为独立框架采用。
|
|
55
55
|
|
|
56
56
|
1. 既有 React Router 应用可以继续按现状运行。TanStack Router 是新脚手架与增量迁移的优先路径,但 React Router 兼容分支仍然保留,团队可以按自己的节奏迁移。
|
|
57
57
|
2. 新建或迁移中的 BFF 能力优先使用 `bff.runtimeFramework: 'effect'`,并将入口实现放在 `api/effect/index.ts`。如果当前应用已经在 `api/lambda/**` 下使用 Hono 处理函数,就继续显式使用 `bff.runtimeFramework: 'hono'`,等准备好再迁移;Hono 仍是受支持的兼容分支。
|
|
58
58
|
3. 将基线契约视为渐进式默认值,而不是一次性强制切换。`MODERN_BASELINE_ENABLE_MF_SSR`、`MODERN_BASELINE_ENABLE_BFF_REQUEST_ID` 和 `MODERN_BASELINE_ENABLE_TELEMETRY_EXPORTERS` 已经提供了按应用、按环境关闭的能力,方便在收敛到目标栈之前逐步过渡。
|
|
59
|
-
4. 这套公开预设现在已经附带显式的发布 / 认证 gate
|
|
59
|
+
4. 这套公开预设现在已经附带显式的发布 / 认证 gate。生成 workspace 会自带 `.github/workflows/ultramodern-workspace-gates.yml`,因此 `pnpm check` 与 `pnpm build` 从第一天开始就是本地接入契约的一部分;CI 会以并行矩阵运行这些基础 gate。
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
公开的 BleedingDev create 包默认从简单路径开始。默认命令会创建一个
|
|
64
|
-
可上线的 UltraModern 单应用,包含 `presetUltramodern(...)`、SSR、
|
|
65
|
-
TanStack Router、Tailwind CSS v4、i18n、Effect BFF、生成质量 gate,以及
|
|
66
|
-
Cloudflare 部署基础:
|
|
61
|
+
旧版生成 workspace 迁移时,以已发布的包 cohort 作为事实来源:
|
|
67
62
|
|
|
68
63
|
```bash
|
|
69
|
-
pnpm dlx @bleedingdev/modern-js-create
|
|
70
|
-
|
|
64
|
+
pnpm dlx @bleedingdev/modern-js-create@latest --help
|
|
65
|
+
pnpm dlx @bleedingdev/modern-js-create@latest catalog --vertical --dry-run
|
|
66
|
+
pnpm dlx @bleedingdev/modern-js-create@latest catalog --vertical
|
|
71
67
|
mise install
|
|
72
68
|
mise exec -- pnpm install
|
|
73
|
-
mise exec -- pnpm
|
|
69
|
+
mise exec -- pnpm check
|
|
70
|
+
mise exec -- pnpm build
|
|
74
71
|
```
|
|
75
72
|
|
|
76
|
-
|
|
73
|
+
每个仓库只使用一种 package-source 策略。已发布的 BleedingDev create 包默认使用
|
|
74
|
+
`--ultramodern-package-source=install`,并把精确 cohort 记录到
|
|
75
|
+
`.modernjs/ultramodern-package-source.json`。`--workspace` 只用于本地 monorepo
|
|
76
|
+
联调未发布包。发布证明和 CI 如果需要证明某个已发布框架版本,应使用
|
|
77
|
+
`--ultramodern-package-version` 固定精确 cohort。
|
|
78
|
+
|
|
79
|
+
安装新 cohort 后,先运行生成的
|
|
80
|
+
`scripts/validate-ultramodern-workspace.mjs` 契约校验,再接受人工改动。topology、
|
|
81
|
+
ownership、package-source、本地 overlay、生成契约、Tailwind prefix 或 Module
|
|
82
|
+
Federation 冲突,都应在对应归属文件中修复,不要手写补丁覆盖生成结果。
|
|
83
|
+
|
|
84
|
+
## 人类工作流
|
|
85
|
+
|
|
86
|
+
公开的 BleedingDev create 包只有一个受支持的生成产品。默认命令会创建一个
|
|
87
|
+
可上线的 UltraModern SuperApp workspace,包含 `presetUltramodern(...)`、
|
|
88
|
+
SSR、TanStack Router、Tailwind CSS v4、i18n、Effect BFF、Module Federation
|
|
89
|
+
topology、生成质量 gate,以及 Cloudflare 部署基础:
|
|
77
90
|
|
|
78
91
|
```bash
|
|
79
|
-
pnpm dlx @bleedingdev/modern-js-create
|
|
80
|
-
cd
|
|
92
|
+
pnpm dlx @bleedingdev/modern-js-create myapp
|
|
93
|
+
cd myapp
|
|
81
94
|
mise install
|
|
82
95
|
mise exec -- pnpm install
|
|
83
|
-
mise exec -- pnpm
|
|
96
|
+
mise exec -- pnpm check
|
|
84
97
|
```
|
|
85
98
|
|
|
86
99
|
workspace 从 shell 和平台契约起步,不强制生成演示业务域。真实业务边界出现后,
|
|
@@ -91,13 +104,94 @@ pnpm dlx @bleedingdev/modern-js-create transportation --vertical
|
|
|
91
104
|
pnpm dlx @bleedingdev/modern-js-create food-delivery --vertical
|
|
92
105
|
pnpm dlx @bleedingdev/modern-js-create payments --vertical
|
|
93
106
|
pnpm dlx @bleedingdev/modern-js-create maps --vertical
|
|
94
|
-
mise exec -- pnpm
|
|
107
|
+
mise exec -- pnpm check
|
|
95
108
|
```
|
|
96
109
|
|
|
97
110
|
`--vertical` 会修改当前 workspace:创建 vertical 包,并更新 topology 元数据、
|
|
98
111
|
ownership 记录、shell Module Federation、开发 overlays、包依赖、生成契约、
|
|
99
112
|
端口、路由归属 i18n、CSS 隔离,以及 vertical 自己拥有的 Effect BFF/client surface。
|
|
100
113
|
|
|
114
|
+
### 生成器自动化
|
|
115
|
+
|
|
116
|
+
自动化脚本可以使用显式 MicroVertical 语法,不必依赖位置参数:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pnpm dlx @bleedingdev/modern-js-create --vertical=transportation
|
|
120
|
+
pnpm dlx @bleedingdev/modern-js-create --vertical-name transportation
|
|
121
|
+
pnpm dlx @bleedingdev/modern-js-create transportation --vertical --dry-run
|
|
122
|
+
pnpm dlx @bleedingdev/modern-js-create transportation --vertical \
|
|
123
|
+
--codesmith-overlay ./generators/vertical-overlay
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
BleedingDev create 包默认安装已发布的包 cohort。本地 monorepo 联调时使用
|
|
127
|
+
`--workspace` 或 `--ultramodern-package-source=workspace`。发布证明与包源自动化还
|
|
128
|
+
可以传入 `--ultramodern-package-source=install`、
|
|
129
|
+
`--ultramodern-package-version`、`--ultramodern-package-registry`、
|
|
130
|
+
`--ultramodern-package-scope` 与
|
|
131
|
+
`--ultramodern-package-name-prefix`。
|
|
132
|
+
|
|
133
|
+
受支持的公开生成器 import 是:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import {
|
|
137
|
+
addUltramodernVertical,
|
|
138
|
+
generateUltramodernWorkspace,
|
|
139
|
+
planUltramodernVertical,
|
|
140
|
+
} from '@modern-js/create/ultramodern-workspace';
|
|
141
|
+
|
|
142
|
+
const workspace = generateUltramodernWorkspace({
|
|
143
|
+
targetDir: '/tmp/my-workspace',
|
|
144
|
+
packageName: 'my-workspace',
|
|
145
|
+
modernVersion: '3.4.0',
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const plan = planUltramodernVertical({
|
|
149
|
+
workspaceRoot: workspace.workspaceRoot,
|
|
150
|
+
name: 'transportation',
|
|
151
|
+
modernVersion: '3.4.0',
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
addUltramodernVertical({
|
|
155
|
+
workspaceRoot: workspace.workspaceRoot,
|
|
156
|
+
name: 'transportation',
|
|
157
|
+
modernVersion: '3.4.0',
|
|
158
|
+
overlays: [{ generator: './generators/vertical-overlay' }],
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
公开结果包含 workspace root、包源、创建的 apps、创建路径、重写路径、分配端口、
|
|
163
|
+
Module Federation 名称、Effect API 前缀、生成契约路径与 warnings。
|
|
164
|
+
MicroVertical dry-run 返回相同结构,并额外包含 `dryRun`、`selectedPort`、
|
|
165
|
+
`moduleFederationRemote`、`effectApiPrefix`、`jsonMutations`、
|
|
166
|
+
`shellDependencyChanges` 与 `generatedContractChanges`;CLI 会输出 JSON,且不写文件。
|
|
167
|
+
|
|
168
|
+
CodeSmith 消费方可以使用 adapter subpath:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import ultramodernCodeSmith from '@modern-js/create/ultramodern-workspace/codesmith';
|
|
172
|
+
|
|
173
|
+
await ultramodernCodeSmith({
|
|
174
|
+
config: {
|
|
175
|
+
mode: 'vertical',
|
|
176
|
+
name: 'transportation',
|
|
177
|
+
workspaceRoot: process.cwd(),
|
|
178
|
+
dryRun: true,
|
|
179
|
+
logResult: true,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
校验会在第一次写文件前执行。缺失或非法的 vertical 名称、已存在 topology 占用
|
|
185
|
+
app ID/路径/包后缀/端口/Module Federation 名称/API 前缀/manifest key、workspace
|
|
186
|
+
JSON 契约缺失或不是对象、Tailwind 前缀冲突,都会报告归属契约。修复 workspace
|
|
187
|
+
契约或选择新的 vertical 名称后再重新运行。
|
|
188
|
+
|
|
189
|
+
Overlays 是显式配置的 CodeSmith 生成器,会在基础 workspace 或 MicroVertical
|
|
190
|
+
生成之后运行。它们只扩展生成结果,不替换、不继承、也不遮蔽基础模板。公开生成器与
|
|
191
|
+
CodeSmith adapter 都是普通 Node 生成器入口。包构建通过 TS-Go 工具链产出声明文件;
|
|
192
|
+
生成出来的 app package 直接安装 TypeScript 7 RC 包线,并且只在本地工具链中使用
|
|
193
|
+
TS-Go,运行时代码不依赖 native-preview compiler 内部实现。
|
|
194
|
+
|
|
101
195
|
### 运行时契约
|
|
102
196
|
|
|
103
197
|
生成应用和 vertical 沿用正常的 Modern.js SSR 路径。SuperApp workspace 在需要
|
|
@@ -106,8 +200,13 @@ Module Federation SSR 时会加入 `server.ssr.moduleFederationAppSSR`,但这
|
|
|
106
200
|
|
|
107
201
|
每个应用都会产出 `src/routes/ultramodern-route-metadata` 和
|
|
108
202
|
`ultramodernLocalisedUrls`。i18n 插件在 `localeDetection.localisedUrls` 中读取它,
|
|
109
|
-
|
|
110
|
-
|
|
203
|
+
这就是在 `localePathRedirect` 之上启用路径片段翻译的显式非空映射。i18n 插件也会从
|
|
204
|
+
`/locales/{{lng}}/{{ns}}.json` 提供动态后端 JSON。路由 owner 需要同时维护本地化路径和
|
|
205
|
+
locale resource JSON。
|
|
206
|
+
|
|
207
|
+
JSON-LD 是可选的路由 metadata,不会自动推断。私有路由和不可索引路由默认不输出
|
|
208
|
+
JSON-LD。公开路由 owner 可以在本地化路径旁显式添加 `jsonLd`,并使用生成的
|
|
209
|
+
`src/routes/ultramodern-jsonld.ts` helper 编写常见 schema.org 结构。
|
|
111
210
|
|
|
112
211
|
生成契约会在 `.modernjs/ultramodern-generated-contract.json` 中写入
|
|
113
212
|
`cssFederation`:
|
|
@@ -125,7 +224,7 @@ Module Federation SSR 时会加入 `server.ssr.moduleFederationAppSSR`,但这
|
|
|
125
224
|
本地 gate:
|
|
126
225
|
|
|
127
226
|
```bash
|
|
128
|
-
mise exec -- pnpm
|
|
227
|
+
mise exec -- pnpm check
|
|
129
228
|
mise exec -- pnpm build
|
|
130
229
|
mise exec -- pnpm cloudflare:build
|
|
131
230
|
```
|
|
@@ -104,7 +104,7 @@ export default RemoteApp;
|
|
|
104
104
|
|
|
105
105
|
## 启动应用
|
|
106
106
|
|
|
107
|
-
现在,生产者应用和消费者应用都已经搭建完毕,我们可以在本地运行 `
|
|
107
|
+
现在,生产者应用和消费者应用都已经搭建完毕,我们可以在本地运行 `modern dev` 启动两个应用。
|
|
108
108
|
|
|
109
109
|
启动后,消费者应用访问 `/remote` 路由时,会进入生产者应用中。访问 `http://localhost:8080/remote`,可以看到页面中已经包含了生产者的远程模块的完整页面。
|
|
110
110
|
|
|
@@ -88,10 +88,10 @@ export default createModuleFederationConfig({
|
|
|
88
88
|
|
|
89
89
|
## 本地验证部署
|
|
90
90
|
|
|
91
|
-
Modern.js 提供了 `
|
|
91
|
+
Modern.js 提供了 `modern deploy` 命令,可以方便生成可运行在 Node.js 环境的产物。
|
|
92
92
|
|
|
93
93
|
```bash
|
|
94
|
-
|
|
94
|
+
modern deploy
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
执行命令后,可以在控制台看到以下输出:
|
|
@@ -154,7 +154,7 @@ export default Index;
|
|
|
154
154
|
|
|
155
155
|
## 启动应用
|
|
156
156
|
|
|
157
|
-
现在,生产者应用和消费者应用都已经搭建完毕,我们可以在本地运行 `
|
|
157
|
+
现在,生产者应用和消费者应用都已经搭建完毕,我们可以在本地运行 `modern dev` 启动两个应用。
|
|
158
158
|
|
|
159
159
|
启动后,消费者中对生产者模块的引入,不会再出现抛错,类型已经下载到消费者应用中。
|
|
160
160
|
|
|
@@ -164,7 +164,7 @@ export default Index;
|
|
|
164
164
|
|
|
165
165
|
访问 `http://localhost:8080/remote`,可以看到页面中已经包含了生产者的远程模块 `Button` 组件。
|
|
166
166
|
|
|
167
|
-
我们也可以在本地执行 `
|
|
167
|
+
我们也可以在本地执行 `modern serve` 来模拟生产环境。
|
|
168
168
|
|
|
169
169
|
因为 Module Federation 插件会自动读取 Modern.js 的 `output.assetPrefix` 配置作为远程模块的访问地址,而该值在生产环境下构建后默认是 `/`。如果不做特殊处理,消费者将从自己的域名下拉取远程模块的入口文件。我们可以添加如下配置:
|
|
170
170
|
|
|
@@ -178,7 +178,7 @@ export default defineConfig({
|
|
|
178
178
|
port: 3051,
|
|
179
179
|
},
|
|
180
180
|
output: {
|
|
181
|
-
// Now this configuration is only used in the local when you run
|
|
181
|
+
// Now this configuration is only used in the local when you run modern serve command.
|
|
182
182
|
// If you want to deploy the application to the platform, use your own domain name.
|
|
183
183
|
// Module federation will automatically write it to mf-manifest.json, which influences consumer to fetch remoteEntry.js.
|
|
184
184
|
assetPrefix: 'http://127.0.0.1:3051',
|
|
@@ -187,10 +187,10 @@ export default defineConfig({
|
|
|
187
187
|
});
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
现在,在生产者中运行 `
|
|
190
|
+
现在,在生产者中运行 `modern build && MODERN_MF_AUTO_CORS=true modern serve`,在消费者中运行 `modern build && modern serve`,即可在本地模拟生产环境,访问到远程模块。
|
|
191
191
|
|
|
192
192
|
:::tip
|
|
193
|
-
在使用 `
|
|
193
|
+
在使用 `modern serve` 命令时,需要在启动生产者项目时携带 `MODERN_MF_AUTO_CORS=true` 环境变量,以自动处理跨域问题,确保消费者可以正常访问生产者的远程模块资源。
|
|
194
194
|
:::
|
|
195
195
|
|
|
196
196
|
上述用例可以参考:[Modern.js & Module Federation 基础用法示例](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/module-federation/base)。
|
|
@@ -23,7 +23,7 @@ Modern.js 内部基于 [Rsbuild](https://v2.rsbuild.rs/) 封装了自身的构
|
|
|
23
23
|
Modern.js 提供 [inspect 命令](/apis/app/commands.html) 用于查看项目最终生成的 Modern.js 配置以及 Rspack 配置。
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
➜ npx
|
|
26
|
+
➜ npx modern inspect
|
|
27
27
|
|
|
28
28
|
Inspect config succeed, open following files to view the content:
|
|
29
29
|
|
|
@@ -334,7 +334,7 @@ export default {
|
|
|
334
334
|
|
|
335
335
|
### tools.rsdoctor
|
|
336
336
|
|
|
337
|
-
**变更内容**:该配置已废弃。v3
|
|
337
|
+
**变更内容**:该配置已废弃。v3 中可通过 [`performance.rsdoctor`](/configure/app/performance/rsdoctor) 显式启用 Rsdoctor 诊断能力。
|
|
338
338
|
|
|
339
339
|
**迁移示例**:
|
|
340
340
|
|
|
@@ -350,7 +350,6 @@ tools: {
|
|
|
350
350
|
// v3
|
|
351
351
|
export default {
|
|
352
352
|
performance: {
|
|
353
|
-
// 生产构建默认启用
|
|
354
353
|
rsdoctor: {
|
|
355
354
|
enabled: true,
|
|
356
355
|
},
|
|
@@ -95,7 +95,7 @@ Modern.js 3.0 不再支持通过 `@bleedingdev/modern-js-create` 创建 Monorepo
|
|
|
95
95
|
**变更内容**:
|
|
96
96
|
|
|
97
97
|
- 在 [v2.53.0](https://github.com/web-infra-dev/modern.js/releases/tag/v2.53.0) 版本中,移除了使用 `@bleedingdev/modern-js-create` 创建 Monorepo 项目的功能
|
|
98
|
-
- 在 [v2.61.0](https://github.com/web-infra-dev/modern.js/releases/tag/v2.61.0) 版本中,移除了使用 `@bleedingdev/modern-js-create` 和 `
|
|
98
|
+
- 在 [v2.61.0](https://github.com/web-infra-dev/modern.js/releases/tag/v2.61.0) 版本中,移除了使用 `@bleedingdev/modern-js-create` 和 `modern new` 命令创建 Modern.js Module 项目的功能
|
|
99
99
|
|
|
100
100
|
**处理方式**:
|
|
101
101
|
|
|
@@ -104,12 +104,12 @@ Modern.js 3.0 不再支持通过 `@bleedingdev/modern-js-create` 创建 Monorepo
|
|
|
104
104
|
|
|
105
105
|
## new 命令和 upgrade 命令移除
|
|
106
106
|
|
|
107
|
-
Modern.js 3.0 移除了 `
|
|
107
|
+
Modern.js 3.0 移除了 `modern new` 和 `modern upgrade` 命令,需要按照文档手动操作。
|
|
108
108
|
|
|
109
109
|
**变更内容**:
|
|
110
110
|
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
111
|
+
- `modern new` 命令在 Modern.js 3.0 中不再支持,无法通过命令添加入口或启用功能
|
|
112
|
+
- `modern upgrade` 命令在 Modern.js 3.0 中不再支持,无法通过命令自动升级依赖
|
|
113
113
|
|
|
114
114
|
**处理方式**:
|
|
115
115
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bleedingdev/modern-js-main-doc",
|
|
3
|
-
"description": "Documentation
|
|
3
|
+
"description": "Documentation for the UltraModern.js framework",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"homepage": "https://github.com/BleedingDev/ultramodern.js#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -16,32 +16,35 @@
|
|
|
16
16
|
"react",
|
|
17
17
|
"framework",
|
|
18
18
|
"modern",
|
|
19
|
-
"modern.js"
|
|
19
|
+
"modern.js",
|
|
20
|
+
"ultramodern.js"
|
|
20
21
|
],
|
|
21
|
-
"version": "3.
|
|
22
|
+
"version": "3.4.0-ultramodern.0",
|
|
22
23
|
"publishConfig": {
|
|
23
24
|
"registry": "https://registry.npmjs.org/",
|
|
24
25
|
"access": "public"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
28
|
"mermaid": "^11.15.0",
|
|
28
|
-
"@modern-js/sandpack-react": "npm:@bleedingdev/modern-js-sandpack-react@3.
|
|
29
|
+
"@modern-js/sandpack-react": "npm:@bleedingdev/modern-js-sandpack-react@3.4.0-ultramodern.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"@rsbuild/plugin-sass": "
|
|
32
|
-
"@rspress/core": "2.0.
|
|
33
|
-
"@rspress/plugin-llms": "2.0.
|
|
34
|
-
"@rspress/shared": "2.0.
|
|
35
|
-
"@shikijs/transformers": "^4.
|
|
32
|
+
"@rsbuild/plugin-sass": "2.0.0",
|
|
33
|
+
"@rspress/core": "2.0.14",
|
|
34
|
+
"@rspress/plugin-llms": "2.0.14",
|
|
35
|
+
"@rspress/shared": "2.0.14",
|
|
36
|
+
"@shikijs/transformers": "^4.2.0",
|
|
36
37
|
"@types/fs-extra": "11.0.4",
|
|
37
|
-
"@types/node": "^
|
|
38
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
38
|
+
"@types/node": "^26.0.0",
|
|
39
|
+
"@typescript/native-preview": "7.0.0-dev.20260624.1",
|
|
39
40
|
"classnames": "^2.5.1",
|
|
40
41
|
"clsx": "^2.1.1",
|
|
41
42
|
"fs-extra": "^11.3.5",
|
|
42
|
-
"react": "^19.2.
|
|
43
|
-
"react-dom": "^19.2.
|
|
44
|
-
"rsbuild-plugin-open-graph": "1.1.
|
|
43
|
+
"react": "^19.2.7",
|
|
44
|
+
"react-dom": "^19.2.7",
|
|
45
|
+
"rsbuild-plugin-open-graph": "1.1.3",
|
|
46
|
+
"ts-node": "^10.9.2",
|
|
47
|
+
"typescript": "^6.0.3"
|
|
45
48
|
},
|
|
46
49
|
"scripts": {
|
|
47
50
|
"dev": "rspress dev",
|
package/rspress.config.ts
CHANGED
|
@@ -5,13 +5,12 @@ import path from 'path';
|
|
|
5
5
|
import { pluginOpenGraph } from 'rsbuild-plugin-open-graph';
|
|
6
6
|
|
|
7
7
|
const docPath = path.join(__dirname, 'docs');
|
|
8
|
+
const staticPath = path.join(__dirname, 'static');
|
|
8
9
|
const siteTitle = 'UltraModern.js 3.0';
|
|
9
10
|
const siteDescription =
|
|
10
11
|
'UltraModern.js 3.0 is a SuperApp framework forked from Modern.js for Effect, TanStack Router, SSR, BFF, and independently deployable Micro Verticals.';
|
|
11
12
|
const socialDescription =
|
|
12
13
|
'A SuperApp framework for Effect, TanStack Router, SSR, BFF, and Micro Verticals.';
|
|
13
|
-
const socialImage =
|
|
14
|
-
'https://lf3-static.bytednsdoc.com/obj/eden-cn/nuvjhpqnuvr/modern-website/banner.jpeg';
|
|
15
14
|
|
|
16
15
|
function normalizeBase(base = '/') {
|
|
17
16
|
const trimmed = base.trim();
|
|
@@ -23,6 +22,14 @@ function normalizeBase(base = '/') {
|
|
|
23
22
|
|
|
24
23
|
// Set by CI for GitHub Pages project sites. Defaults to root for local dev/custom domains.
|
|
25
24
|
const docsBase = normalizeBase(process.env.DOCS_BASE);
|
|
25
|
+
const docsOrigin = (
|
|
26
|
+
process.env.DOCS_ORIGIN || 'https://bleedingdev.github.io'
|
|
27
|
+
).replace(/\/+$/, '');
|
|
28
|
+
const siteUrl = new URL(docsBase, `${docsOrigin}/`).toString();
|
|
29
|
+
const socialImage = new URL('img/social-card.svg', siteUrl).toString();
|
|
30
|
+
const faviconUrl = new URL('img/favicon.ico', siteUrl).toString();
|
|
31
|
+
const docsAsset = (assetPath: string) =>
|
|
32
|
+
`${docsBase}${assetPath.replace(/^\//, '')}`;
|
|
26
33
|
|
|
27
34
|
export default defineConfig({
|
|
28
35
|
root: docPath,
|
|
@@ -30,8 +37,8 @@ export default defineConfig({
|
|
|
30
37
|
title: siteTitle,
|
|
31
38
|
description: siteDescription,
|
|
32
39
|
base: docsBase,
|
|
33
|
-
logo: '
|
|
34
|
-
icon:
|
|
40
|
+
logo: docsAsset('/img/logo.svg'),
|
|
41
|
+
icon: faviconUrl,
|
|
35
42
|
lang: 'en',
|
|
36
43
|
themeDir: path.join(__dirname, 'src'),
|
|
37
44
|
markdown: {
|
|
@@ -121,6 +128,11 @@ export default defineConfig({
|
|
|
121
128
|
output: {
|
|
122
129
|
dataUriLimit: 0,
|
|
123
130
|
},
|
|
131
|
+
server: {
|
|
132
|
+
publicDir: {
|
|
133
|
+
name: staticPath,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
124
136
|
dev: {
|
|
125
137
|
lazyCompilation: process.env.LAZY !== 'false',
|
|
126
138
|
},
|
|
@@ -139,7 +151,7 @@ export default defineConfig({
|
|
|
139
151
|
// While site name is site wide
|
|
140
152
|
siteName: siteTitle,
|
|
141
153
|
type: 'website',
|
|
142
|
-
url:
|
|
154
|
+
url: siteUrl,
|
|
143
155
|
image: socialImage,
|
|
144
156
|
description: socialDescription,
|
|
145
157
|
twitter: {
|
|
@@ -81,15 +81,15 @@ export default function Footer() {
|
|
|
81
81
|
items: [
|
|
82
82
|
{
|
|
83
83
|
label: t('changelog'),
|
|
84
|
-
to: 'https://github.com/
|
|
84
|
+
to: 'https://github.com/BleedingDev/ultramodern.js/releases',
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
87
|
label: 'GitHub Issues',
|
|
88
|
-
to: 'https://github.com/
|
|
88
|
+
to: 'https://github.com/BleedingDev/ultramodern.js/issues',
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
label: t('githubDiscussion'),
|
|
92
|
-
to: 'https://github.com/
|
|
92
|
+
to: 'https://github.com/BleedingDev/ultramodern.js/discussions',
|
|
93
93
|
},
|
|
94
94
|
],
|
|
95
95
|
},
|