@modern-js/main-doc 2.60.1 → 2.60.3
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/apis/app/commands.mdx +6 -21
- package/docs/en/components/deploy-command.mdx +14 -0
- package/docs/en/components/serve-command.mdx +22 -0
- package/docs/en/configure/app/dev/watch-files.mdx +13 -6
- package/docs/en/configure/app/output/copy.mdx +4 -1
- package/docs/en/configure/app/output/inline-scripts.mdx +1 -1
- package/docs/en/configure/app/output/inline-styles.mdx +1 -1
- package/docs/en/configure/app/runtime/router.mdx +11 -3
- package/docs/en/configure/app/runtime/state.mdx +0 -2
- package/docs/en/guides/concept/_meta.json +1 -1
- package/docs/en/guides/concept/server.mdx +35 -0
- package/docs/en/guides/topic-detail/_meta.json +6 -0
- package/docs/en/guides/topic-detail/module-federation/_meta.json +1 -0
- package/docs/en/guides/topic-detail/module-federation/application.mdx +112 -0
- package/docs/en/guides/topic-detail/module-federation/deploy.mdx +28 -0
- package/docs/en/guides/topic-detail/module-federation/introduce.mdx +35 -0
- package/docs/en/guides/topic-detail/module-federation/ssr.mdx +31 -0
- package/docs/en/guides/topic-detail/module-federation/usage.mdx +180 -0
- package/docs/zh/apis/app/commands.mdx +6 -21
- package/docs/zh/components/deploy-command.mdx +14 -0
- package/docs/zh/components/serve-command.mdx +22 -0
- package/docs/zh/configure/app/dev/watch-files.mdx +13 -6
- package/docs/zh/configure/app/output/copy.mdx +4 -2
- package/docs/zh/configure/app/output/inline-scripts.mdx +1 -1
- package/docs/zh/configure/app/output/inline-styles.mdx +1 -1
- package/docs/zh/configure/app/runtime/router.mdx +10 -4
- package/docs/zh/configure/app/runtime/state.mdx +0 -2
- package/docs/zh/guides/concept/_meta.json +1 -1
- package/docs/zh/guides/concept/server.mdx +35 -0
- package/docs/zh/guides/topic-detail/_meta.json +6 -0
- package/docs/zh/guides/topic-detail/module-federation/_meta.json +1 -0
- package/docs/zh/guides/topic-detail/module-federation/application.mdx +112 -0
- package/docs/zh/guides/topic-detail/module-federation/deploy.mdx +28 -0
- package/docs/zh/guides/topic-detail/module-federation/introduce.mdx +35 -0
- package/docs/zh/guides/topic-detail/module-federation/ssr.mdx +31 -0
- package/docs/zh/guides/topic-detail/module-federation/usage.mdx +181 -0
- package/docs/zh/plugin/introduction.mdx +4 -4
- package/i18n.json +4 -0
- package/package.json +4 -4
@@ -0,0 +1,14 @@
|
|
1
|
+
## modern deploy
|
2
|
+
|
3
|
+
`modern deploy` 命令,用于生成部署平台需要的产物。
|
4
|
+
|
5
|
+
```bash
|
6
|
+
Usage: modern deploy [options]
|
7
|
+
|
8
|
+
Options:
|
9
|
+
-c --config <config> 指定配置文件路径,可以为相对路径或绝对路径
|
10
|
+
-s --skip-build 跳过构建阶段
|
11
|
+
-h, --help 显示命令帮助
|
12
|
+
```
|
13
|
+
|
14
|
+
详细内容可以参考 [部署应用](/guides/basic-features/deploy)。
|
@@ -0,0 +1,22 @@
|
|
1
|
+
## modern serve
|
2
|
+
|
3
|
+
`modern serve` 命令用于在生产环境下启动 Modern.js 工程, 也可以用于在本地预览生产环境构建的产物。注意你需要提前执行 [`build`](/apis/app/commands#modern-build) 命令构建出对应产物。
|
4
|
+
|
5
|
+
```bash
|
6
|
+
Usage: modern serve [options]
|
7
|
+
|
8
|
+
Options:
|
9
|
+
-c --config <config> 指定配置文件路径,可以为相对路径或绝对路径
|
10
|
+
-h, --help 显示命令帮助
|
11
|
+
--api-only 仅启动 API 接口服务
|
12
|
+
```
|
13
|
+
|
14
|
+
默认情况下,应用将会在 `localhost:8080` 启动,可以通过 `server.port` 修改 Server 端口号:
|
15
|
+
|
16
|
+
```js
|
17
|
+
export default defineConfig({
|
18
|
+
server: {
|
19
|
+
port: 8081,
|
20
|
+
},
|
21
|
+
});
|
22
|
+
```
|
@@ -8,12 +8,19 @@ configName: dev.watchFiles
|
|
8
8
|
- **类型:**
|
9
9
|
|
10
10
|
```ts
|
11
|
-
type WatchFiles =
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
type WatchFiles =
|
12
|
+
| {
|
13
|
+
paths: string | string[];
|
14
|
+
type?: 'reload-page';
|
15
|
+
// chokidar 选项
|
16
|
+
options?: WatchOptions;
|
17
|
+
}
|
18
|
+
| {
|
19
|
+
paths: string | string[];
|
20
|
+
type?: 'reload-server';
|
21
|
+
};
|
22
|
+
|
23
|
+
type WatchFilesConfig = WatchFiles | WatchFiles[];
|
17
24
|
```
|
18
25
|
|
19
26
|
- **默认值:** `undefined`
|
@@ -1,5 +1,6 @@
|
|
1
1
|
---
|
2
2
|
title: copy
|
3
|
+
configName: output.copy
|
3
4
|
---
|
4
5
|
|
5
6
|
# output.copy
|
@@ -7,7 +8,8 @@ title: copy
|
|
7
8
|
- **类型:** `Rspack.CopyRspackPluginOptions | Rspack.CopyRspackPluginOptions['patterns']`
|
8
9
|
- **默认值:** `undefined`
|
9
10
|
|
10
|
-
|
11
11
|
将指定的文件或目录拷贝到构建输出目录中,基于 [rspack.CopyRspackPlugin](https://rspack.dev/zh/plugins/rspack/copy-rspack-plugin) 实现。
|
12
12
|
|
13
|
-
|
13
|
+
import RsbuildConig from '@site-docs/components/rsbuild-config-tooltip';
|
14
|
+
|
15
|
+
<RsbuildConig />
|
@@ -26,7 +26,7 @@ type InlineScripts =
|
|
26
26
|
用来控制是否用 `<script>` 标签将产物中的 script 文件(.js 文件)inline 到 HTML 中。
|
27
27
|
|
28
28
|
:::tip
|
29
|
-
当使用约定式路由时,如果开启了这个选项,需要将 [output.splitRouteChunks](
|
29
|
+
当使用约定式路由时,如果开启了这个选项,需要将 [output.splitRouteChunks](/configure/app/output/split-route-chunks) 设置为 false。
|
30
30
|
:::
|
31
31
|
|
32
32
|
import RsbuildConig from '@site-docs/components/rsbuild-config-tooltip';
|
@@ -26,7 +26,7 @@ type InlineStyles =
|
|
26
26
|
用来控制是否用 `<style>` 标签将产物中的 style 文件(.css 文件)inline 到 HTML 中。
|
27
27
|
|
28
28
|
:::tip
|
29
|
-
当使用约定式路由时,如果开启了这个选项,需要将 [output.splitRouteChunks](
|
29
|
+
当使用约定式路由时,如果开启了这个选项,需要将 [output.splitRouteChunks](/configure/app/output/split-route-chunks) 设置为 false。
|
30
30
|
:::
|
31
31
|
|
32
32
|
import RsbuildConig from '@site-docs/components/rsbuild-config-tooltip';
|
@@ -8,14 +8,16 @@ import RouterLegacyTip from "@site-docs/components/router-legacy-tip"
|
|
8
8
|
|
9
9
|
<RouterLegacyTip />
|
10
10
|
|
11
|
-
# runtime.router
|
12
|
-
|
13
11
|
- **类型:** `boolean | Object`
|
14
12
|
- **默认值:** `false`
|
15
13
|
|
16
|
-
|
14
|
+
该值在项目创建时被设置为 `true`,支持使用 Modern.js 默认提供的[约定式路由](/guides/concept/entries.html#约定式路由)进行路由管理。
|
15
|
+
|
16
|
+
如果希望使用[自控式路由](/guides/concept/entries.html#自控式路由),请移除该值,或将该值设置为 `false`。
|
17
17
|
|
18
|
-
|
18
|
+
:::note
|
19
|
+
`router` 的所有子配置都只会在使用约定式路由时生效。
|
20
|
+
:::
|
19
21
|
|
20
22
|
## basename
|
21
23
|
|
@@ -24,6 +26,10 @@ import RouterLegacyTip from "@site-docs/components/router-legacy-tip"
|
|
24
26
|
|
25
27
|
设置客户端路由的 `basename`,通常用于应用需要部署在域名非根路径下的场景。
|
26
28
|
|
29
|
+
:::tip
|
30
|
+
推荐使用 [`server.baseUrl`](/configure/app/server/base-url) 进行配置。
|
31
|
+
:::
|
32
|
+
|
27
33
|
## supportHtml5History
|
28
34
|
|
29
35
|
- **类型:** `boolean`
|
@@ -1 +1 @@
|
|
1
|
-
["entries", "builder"]
|
1
|
+
["entries", "builder", "server"]
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Web 服务器
|
2
|
+
|
3
|
+
Modern.js 为应用提供了内置的 Web 服务器,可以被运行在任何拥有 Node.js 的容器环境中。无论是在本地开发环境中执行 `dev` 命令,或是执行 `build && serve` 命令运行生成环境产物,或是官方的部署方案,都是通过这个 Web 服务器来托管应用。
|
4
|
+
|
5
|
+
## 底层依赖
|
6
|
+
|
7
|
+
Modern.js 基于 [Hono 框架](https://hono.dev/) 搭建了自己的 Web 服务器。Hono 是一个小型、简单且超快速的基于 Web 标准的框架,它能在任何 JavaScript 运行时上运行。
|
8
|
+
|
9
|
+
## 开发 & 生产
|
10
|
+
|
11
|
+
Modern.js 开发环境和生产环境的 Web 服务器流程是完全同构的,你无需担心开发环境和生产环境的差异。
|
12
|
+
|
13
|
+
在 [构建工具](/guides/concept/builder) 一节我们提到,Modern.js 底层构建能力由 Rsbuild 提供,而部分开发环境的服务端能力是与构建工具耦合的,例如 HMR。Modern.js 需要复用 Rsbuild Dev Server 的能力。
|
14
|
+
|
15
|
+
在开发环境,Modern.js 直接使用了 Rsbuild 提供的中间件,包含 HMR、Proxy 等开发阶段需要的能力。同时,Modern.js 在这之上提供了 Mock、路由、渲染等能力:
|
16
|
+
|
17
|
+

|
18
|
+
|
19
|
+
因此,在 Modern.js 中开发环境只是在生产环境上增加了中间件。生产环境的所有能力,在开发环境中也同样适用,两者不会产生割裂。
|
20
|
+
|
21
|
+
:::tip
|
22
|
+
静态资源文件能够直接被 Modern.js 的服务器托管,但在生产环境中,强烈推荐将这些内容上传到 CDN。
|
23
|
+
:::
|
24
|
+
|
25
|
+
## 在 CI 环境中运行
|
26
|
+
|
27
|
+
Modern.js 支持在任何 Node.js 环境运行构建产物。在 CI 环境中,通常情况下已经安装了应用全部的依赖。
|
28
|
+
|
29
|
+
你可以执行 [`modern build`](/apis/app/commands#modern-build) 来构建应用,执行 [`modern serve`](/apis/app/commands#modern-serve) 命令来运行 Web 服务器,启动 Modern.js 应用。
|
30
|
+
|
31
|
+
## 在生产环境中运行
|
32
|
+
|
33
|
+
在部署到生产环境时,产物体积应该尽可能小,而上述在 CI 中运行的方案,会保留原项目的所有产物。因此在生产环境,不推荐通过上述命令运行应用。
|
34
|
+
|
35
|
+
Modern.js 提供了独立的部署方案,当运行 [`modern deploy`](/apis/app/commands#modern-deploy) 命令时,产物中会包含可运行 Web 服务器的入口文件。
|
@@ -0,0 +1 @@
|
|
1
|
+
["introduce", "usage", "application", "ssr", "deploy"]
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# 应用级别模块
|
2
|
+
|
3
|
+
Modern.js 提供了运行时 API,支持快速从应用中导出应用级别的 Module Federation 模块。
|
4
|
+
|
5
|
+
我们以 [使用模块联邦](/guides/topic-detail/module-federation/usage) 创建的应用为例,进一步说明如何导入应用级别模块。
|
6
|
+
|
7
|
+
## 安装依赖
|
8
|
+
|
9
|
+
在原本应用的基础上,我们需要安装 `@module-federation/bridge-react` 依赖,用于使用 Bridge 加载应用级别模块。
|
10
|
+
|
11
|
+
import { PackageManagerTabs } from '@theme';
|
12
|
+
|
13
|
+
<PackageManagerTabs command="add @module-federation/bridge-react" />
|
14
|
+
|
15
|
+
## 生产者导出模块
|
16
|
+
|
17
|
+
和直接导出组件级别的模块不同,我们需要为应用级别模块创建一个独立的入口来作为 `Module Federation` 的导出。
|
18
|
+
|
19
|
+
我们创建 `src/export-App.tsx` 文件:
|
20
|
+
|
21
|
+
:::note
|
22
|
+
这里可以是任意的文件名,Modern.js 没有做强制约定。
|
23
|
+
:::
|
24
|
+
|
25
|
+
```ts title="src/export-App.tsx"
|
26
|
+
import '@modern-js/runtime/registry/main'; // 这一行必须引入,它会默认导入微前端运行时依赖
|
27
|
+
import { render } from '@modern-js/runtime/browser';
|
28
|
+
import { createRoot } from '@modern-js/runtime/react';
|
29
|
+
import { createBridgeComponent } from '@module-federation/bridge-react';
|
30
|
+
|
31
|
+
const ModernRoot = createRoot();
|
32
|
+
export const provider = createBridgeComponent({
|
33
|
+
rootComponent: ModernRoot,
|
34
|
+
render: (Component, dom) => render(Component, dom),
|
35
|
+
});
|
36
|
+
|
37
|
+
export default provider;
|
38
|
+
```
|
39
|
+
|
40
|
+
该文件会将 `main` 入口的应用根组件传递给 Bridge API,并通过 Bridge 将调用渲染函数将其渲染到指定的节点上。
|
41
|
+
|
42
|
+
接下来,我们配置 `module-federation.config.ts`,将导出修改为 `src/export-App.tsx`:
|
43
|
+
|
44
|
+
```ts title="module-federation.config.ts"
|
45
|
+
import { createModuleFederationConfig } from '@module-federation/modern-js';
|
46
|
+
|
47
|
+
export default createModuleFederationConfig({
|
48
|
+
name: 'remote',
|
49
|
+
filename: 'remoteEntry.js',
|
50
|
+
exposes: {
|
51
|
+
'./app': './src/export-App.tsx',
|
52
|
+
},
|
53
|
+
shared: {
|
54
|
+
react: { singleton: true },
|
55
|
+
'react-dom': { singleton: true },
|
56
|
+
},
|
57
|
+
});
|
58
|
+
```
|
59
|
+
|
60
|
+
:::info
|
61
|
+
[`createBridgeComponent`](https://module-federation.io/zh/practice/bridge/react-bridge.html#createbridgecomponent) 用于导出应用级别模块,Modern.js 相关 API 可以查看 [createRoot](/apis/app/runtime/core/create-root)、[render](/apis/app/runtime/core/render)。
|
62
|
+
:::
|
63
|
+
|
64
|
+
## 消费者使用模块
|
65
|
+
|
66
|
+
然后我们修改消费者配置,移除之前创建的的路由文件 `src/routes/remote/page.tsx`。
|
67
|
+
|
68
|
+
我们希望所有访问到 `/remote` 的路由都能被进入上述应用级别模块中,因此我们重新添加 `src/routes/remote/$.tsx`。
|
69
|
+
|
70
|
+
:::note
|
71
|
+
如果你还不了解 `$.tsx` 的能力,可以阅读 [通配路由](/guides/basic-features/routes.html#通配路由)。
|
72
|
+
:::
|
73
|
+
|
74
|
+
```tsx title="src/routes/remote/$.tsx"
|
75
|
+
import { createRemoteComponent } from '@module-federation/bridge-react';
|
76
|
+
import { loadRemote } from '@module-federation/modern-js/runtime';
|
77
|
+
|
78
|
+
const ErrorBoundary = (info?: { error: { message: string } }) => {
|
79
|
+
return (
|
80
|
+
<div>
|
81
|
+
<h2>This is ErrorBoundary Component, Something went wrong:</h2>
|
82
|
+
<pre style={{ color: 'red' }}>{info?.error.message}</pre>
|
83
|
+
</div>
|
84
|
+
);
|
85
|
+
};
|
86
|
+
const Loading = <div>loading...</div>;
|
87
|
+
const RemoteApp = createRemoteComponent({
|
88
|
+
loader: () => loadRemote('remote/app'),
|
89
|
+
fallback: ErrorBoundary,
|
90
|
+
loading: Loading,
|
91
|
+
});
|
92
|
+
|
93
|
+
export default RemoteApp;
|
94
|
+
```
|
95
|
+
|
96
|
+
:::info
|
97
|
+
[`createRemoteComponent`](https://module-federation.io/zh/practice/bridge/react-bridge.html#createremotecomponent) 用于加载应用级别模块。
|
98
|
+
:::
|
99
|
+
|
100
|
+
## 启动应用
|
101
|
+
|
102
|
+
现在,生产者应用和消费者应用都已经搭建完毕,我们可以在本地运行 `modern dev` 启动两个应用。
|
103
|
+
|
104
|
+
启动后,消费者应用访问 `/remote` 路由时,会进入生产者应用中。访问 `http://localhost:8080/remote`,可以看到页面中已经包含了生产者的远程模块的完整页面。
|
105
|
+
|
106
|
+
你可以在生产者应用中,创建新的路由文件,并在代码中添加路由导航,可以发现这些功能也能够正常运行。
|
107
|
+
|
108
|
+
上述用例可以参考:[Modern.js & Module Federation 应用级别模块](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/module-federation/app-export)。
|
109
|
+
|
110
|
+
## 相关文档
|
111
|
+
|
112
|
+
- [Module Federation Bridge](https://module-federation.io/zh/practice/bridge/index.html)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# 部署
|
2
|
+
|
3
|
+
通常情况下,部署 Module Federation 应用,需要在消费者上将远程模块地址,调整为其线上地址。
|
4
|
+
|
5
|
+
例如已经将生产者部署到 `https://my-remote-module` 这个域名下,可以这样修改消费者的 `module-federation.config.ts` 文件:
|
6
|
+
|
7
|
+
```ts title="module-federation.config.ts"
|
8
|
+
import { createModuleFederationConfig } from '@module-federation/modern-js';
|
9
|
+
|
10
|
+
export default createModuleFederationConfig({
|
11
|
+
name: 'host',
|
12
|
+
remotes: {
|
13
|
+
remote: 'remote@http://my-remote-module/mf-manifest.json',
|
14
|
+
},
|
15
|
+
shared: {
|
16
|
+
react: { singleton: true },
|
17
|
+
'react-dom': { singleton: true },
|
18
|
+
},
|
19
|
+
});
|
20
|
+
```
|
21
|
+
|
22
|
+
此时,消费者将加载生产环境的 `remote` 模块的 `manifest` 配置文件。
|
23
|
+
|
24
|
+
## 通过平台部署
|
25
|
+
|
26
|
+
上述部署方式只是最简单的实践,在真实场景还有很多限制,例如版本管理、发布时序等。在字节跳动内部,我们在部署平台上搭建了 Module Federation 应用的部署流程,可以帮助开发者解决这些问题。
|
27
|
+
|
28
|
+
我们会持续关注社区里类似功能的平台,在未来完善 Modern.js + Module Federation 在这些类平台上的部署文档。
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# 简介
|
2
|
+
|
3
|
+
模块联邦(Module Federation)是一种 JavaScript 应用分治的架构模式,它允许你在多个 JavaScript 应用之间共享代码和资源。
|
4
|
+
|
5
|
+
在这种分治的模式下,可以帮助你提升应用程序的性能,增强代码可维护性等。
|
6
|
+
|
7
|
+
## Module Federation 2.0
|
8
|
+
|
9
|
+
Module Federation 作为 Webpack 5 推出的重磅功能,自发布以来已经三年有余。在今年,字节跳动与 Module Federation 的作者 [@Zack Jackson](https://github.com/ScriptedAlchemy) 以及社区成员共同推出了 **Module Federation 2.0**。
|
10
|
+
|
11
|
+
Module Federation 2.0 基于字节跳动内部实践以及 Module Federation 原有社区生态,解决了原先版本中的诸多问题。
|
12
|
+
|
13
|
+
在字节跳动内部,基于 Modern.js 的框架已经与 Module Federation 2.0 进行了深度集成。我们正在逐步将这些功能集成到 Modern.js 中,希望与社区开发者共同探索未来。
|
14
|
+
|
15
|
+
:::info
|
16
|
+
参考 [Module Federation 2.0 发布](https://module-federation.io/zh/blog/announcement.html) 获取更多相关内容。
|
17
|
+
:::
|
18
|
+
|
19
|
+
## Modern.js MF 插件
|
20
|
+
|
21
|
+
基于字节跳动内部实践,Module Federation 团队官方提供了 [Modern.js 插件](https://www.npmjs.com/package/@module-federation/modern-js),帮助开发者更方便的使用 Module Federation。
|
22
|
+
|
23
|
+
插件会识别当前构建引擎(Webpack 或 Rspack),在 Modern.js 应用中注入 Module Federation 对应插件,并自动处理构建配置、添加运行时代码等。
|
24
|
+
|
25
|
+
同时,插件还支持在 Modern.js SSR 应用中使用 Module Federation,提供更好的性能体验。
|
26
|
+
|
27
|
+
详细内容可以参考 [使用 Module Federation](/guides/topic-detail/module-federation/usage)、[Module Federation 服务端渲染](/guides/topic-detail/module-federation/ssr)。
|
28
|
+
|
29
|
+
## 应用维度模块
|
30
|
+
|
31
|
+
**应用级别模块**是具备应用的框架渲染能力及路由能力,能像应用一样运行的模块。应用级别模块是在**微前端框架**中非常重要的能力,提供跨应用框架(React、Vue)加载和渲染的能力,支持加载带路由的模块。
|
32
|
+
|
33
|
+
Module Federation 2.0 提供了 [Bridge](https://module-federation.io/zh/practice/bridge/index.html) 的能力,用于加载应用级别模块。
|
34
|
+
|
35
|
+
Modern.js 基于 Brdige 和自身内部实现提供了 API,可以非常简单的导出应用级别模块。详细内容可以参考 [应用级别模块](/guides/topic-detail/module-federation/application)。
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# 服务端渲染
|
2
|
+
|
3
|
+
`@module-federation/modern-js` 提供了非常强大的能力,开发者可以非常方便的在 Modern.js 应用中,组合使用 Module Federation 和服务端渲染(SSR)的能力。
|
4
|
+
|
5
|
+
## 开启 SSR
|
6
|
+
|
7
|
+
我们以 [使用模块联邦](/guides/topic-detail/module-federation/usage) 创建的应用为例,只需要在生产者和消费者上,都添加 `server.ssr` 配置即可:
|
8
|
+
|
9
|
+
```ts title="modern.config.ts"
|
10
|
+
import { appTools, defineConfig } from '@modern-js/app-tools';
|
11
|
+
|
12
|
+
export default defineConfig({
|
13
|
+
server: {
|
14
|
+
ssr: {
|
15
|
+
mode: 'stream',
|
16
|
+
},
|
17
|
+
},
|
18
|
+
}
|
19
|
+
```
|
20
|
+
|
21
|
+
为更好的性能体验,我们仅支持 Streaming SSR 情况使用这种能力组合。
|
22
|
+
|
23
|
+
:::warning
|
24
|
+
目前 `@module-federation/bridge-react` 未兼容 Node 环境,你必须从依赖中移除它,才能正常使用 Module Federation 和服务端渲染。这意味着 Bridge 无法和服务端渲染配合使用。
|
25
|
+
:::
|
26
|
+
|
27
|
+
## 数据获取
|
28
|
+
|
29
|
+
:::note
|
30
|
+
敬请期待
|
31
|
+
:::
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# 开始使用
|
2
|
+
|
3
|
+
在 Modern.js 中使用 Module Federation 我们推荐使用官方插件 `@module-federation/modern-js`。
|
4
|
+
|
5
|
+
本章节将会介绍如何通过官方插件搭含生产者应用与消费者应用,我们首先根据 [Modern.js 快速上手](/guides/get-started/quick-start) 创建两个应用。
|
6
|
+
|
7
|
+
## 安装插件
|
8
|
+
|
9
|
+
完成应用创建后,我们分别为两个项目安装插件:
|
10
|
+
|
11
|
+
import { PackageManagerTabs } from '@theme';
|
12
|
+
|
13
|
+
<PackageManagerTabs command="add @module-federation/modern-js" />
|
14
|
+
|
15
|
+
## 注册插件
|
16
|
+
|
17
|
+
安装插件后,你需要在 `modern.config.js` 中注册插件:
|
18
|
+
|
19
|
+
```ts
|
20
|
+
import { appTools, defineConfig } from '@modern-js/app-tools';
|
21
|
+
import { moduleFederationPlugin } from '@module-federation/modern-js';
|
22
|
+
|
23
|
+
export default defineConfig({
|
24
|
+
runtime: {
|
25
|
+
router: true,
|
26
|
+
},
|
27
|
+
plugins: [
|
28
|
+
appTools({
|
29
|
+
bundler: 'rspack',
|
30
|
+
}),
|
31
|
+
moduleFederationPlugin(),
|
32
|
+
],
|
33
|
+
});
|
34
|
+
|
35
|
+
```
|
36
|
+
|
37
|
+
## 生产者导出模块
|
38
|
+
|
39
|
+
接下来,我们先修改生产者的代码,导出 Module Federation 模块。
|
40
|
+
|
41
|
+
我们创建 `src/components/Button.tsx` 文件,导出一个 Button 组件:
|
42
|
+
|
43
|
+
```tsx title="src/components/Button.tsx"
|
44
|
+
import React from 'react';
|
45
|
+
|
46
|
+
export const Button = () => {
|
47
|
+
return <button type="button">Remote Button</button>;
|
48
|
+
};
|
49
|
+
```
|
50
|
+
|
51
|
+
随后,在项目根目录添加 `module-federation.config.ts`,配置 Module Federation 模块的名称、共享依赖和导出内容:
|
52
|
+
|
53
|
+
```ts title="module-federation.config.ts"
|
54
|
+
import { createModuleFederationConfig } from '@module-federation/modern-js';
|
55
|
+
|
56
|
+
export default createModuleFederationConfig({
|
57
|
+
name: 'remote',
|
58
|
+
filename: 'remoteEntry.js',
|
59
|
+
exposes: {
|
60
|
+
'./Button': './src/components/Button.tsx',
|
61
|
+
},
|
62
|
+
shared: {
|
63
|
+
react: { singleton: true },
|
64
|
+
'react-dom': { singleton: true },
|
65
|
+
},
|
66
|
+
});
|
67
|
+
```
|
68
|
+
|
69
|
+
另外,我们还需要修改 `modern.config.ts`,为生产者提供一个开发环境的端口,让消费者可以通过此端口访问生产者的资源:
|
70
|
+
|
71
|
+
```ts title="modern.config.ts"
|
72
|
+
import { appTools, defineConfig } from '@modern-js/app-tools';
|
73
|
+
import { moduleFederationPlugin } from '@module-federation/modern-js';
|
74
|
+
|
75
|
+
export default defineConfig({
|
76
|
+
dev: {
|
77
|
+
port: 3051,
|
78
|
+
},
|
79
|
+
runtime: {
|
80
|
+
router: true,
|
81
|
+
},
|
82
|
+
plugins: [
|
83
|
+
appTools({
|
84
|
+
bundler: 'rspack',
|
85
|
+
}),
|
86
|
+
moduleFederationPlugin(),
|
87
|
+
],
|
88
|
+
});
|
89
|
+
```
|
90
|
+
|
91
|
+
## 消费者使用模块
|
92
|
+
|
93
|
+
现在,我们修改消费者的代码,使用生产者导出的模块。
|
94
|
+
|
95
|
+
在项目根目录添加 `module-federation.config.ts`,配置 Module Federation 模块的名称、共享依赖和使用的远程模块:
|
96
|
+
|
97
|
+
```ts title="module-federation.config.ts"
|
98
|
+
import { createModuleFederationConfig } from '@module-federation/modern-js';
|
99
|
+
|
100
|
+
export default createModuleFederationConfig({
|
101
|
+
name: 'host',
|
102
|
+
remotes: {
|
103
|
+
remote: 'remote@http://localhost:3051/mf-manifest.json',
|
104
|
+
},
|
105
|
+
shared: {
|
106
|
+
react: { singleton: true },
|
107
|
+
'react-dom': { singleton: true },
|
108
|
+
},
|
109
|
+
});
|
110
|
+
```
|
111
|
+
|
112
|
+
`mf-manifest.json` 是生产者在打包后产出的文件,包含了生产者导出的所有模块信息。
|
113
|
+
|
114
|
+
我们创建新的路由文件 `src/routes/remote/page.tsx`,引入生产者模块:
|
115
|
+
|
116
|
+
```tsx title="src/routes/remote/page.tsx"
|
117
|
+
import React, { useState, Suspense } from 'react';
|
118
|
+
import { Button } from 'remote/Button';
|
119
|
+
|
120
|
+
const Index = (): JSX.Element => {
|
121
|
+
return (
|
122
|
+
<div>
|
123
|
+
<Suspense fallback={<div>Loading...</div>}>
|
124
|
+
<Button />
|
125
|
+
</Suspense>
|
126
|
+
</div>
|
127
|
+
);
|
128
|
+
};
|
129
|
+
|
130
|
+
export default Index;
|
131
|
+
```
|
132
|
+
|
133
|
+
此时 `remote/Button` 引入会出现类型错误,这是因为本地没有远程模块的类型。Module Federation 2.0 提供了 [类型提示](https://module-federation.io/zh/guide/basic/type-prompt.html) 的能力,会在生产者构建时自动生成远程模块的类型定义,在消费者构建时自动下载。
|
134
|
+
|
135
|
+
为此我们需要在 `tsconfig.json` 中添加新的 `path`,保证类型生效:
|
136
|
+
|
137
|
+
```json title="tsconfig.json"
|
138
|
+
{
|
139
|
+
"compilerOptions": {
|
140
|
+
"paths": {
|
141
|
+
"*": ["./@mf-types/*"]
|
142
|
+
}
|
143
|
+
}
|
144
|
+
}
|
145
|
+
```
|
146
|
+
|
147
|
+
:::tip
|
148
|
+
在消费者中,我们通过 `remote/Button` 来引用远程模块。这里简单介绍下这个路径具体代表了什么,可以先将它抽象成 `[remoteAlias]/[remoteExpose]`。
|
149
|
+
|
150
|
+
第一段 `remoteAlias` 是生产者在消费者中的别名,它是消费者 `module-federation.config.ts` 中配置的 `remotes` 字段的 `key`:
|
151
|
+
|
152
|
+
```ts
|
153
|
+
{
|
154
|
+
remotes: {
|
155
|
+
[remoteAlias]: '[remoteModuleName]@[URL_ADDRESS]',
|
156
|
+
}
|
157
|
+
}
|
158
|
+
```
|
159
|
+
|
160
|
+
这里我们也将远程地址抽象为 `[remoteModuleName]@[URL_ADDRESS]`,`@` 前的部分必须对应生产者的模块名。
|
161
|
+
|
162
|
+
第二段 `remoteExpose` 是生产者在 `module-federation.config.ts` 中配置的 `exposes` 字段的 `key`。
|
163
|
+
:::
|
164
|
+
|
165
|
+
## 启动应用
|
166
|
+
|
167
|
+
现在,生产者应用和消费者应用都已经搭建完毕,我们可以在本地运行 `modern dev` 启动两个应用。
|
168
|
+
|
169
|
+
启动后,消费者中对生产者模块的引入,不会再出现抛错,类型已经下载到消费者应用中。
|
170
|
+
|
171
|
+
:::note
|
172
|
+
修改生产者代码后,消费者会自动拉取生产者的类型。
|
173
|
+
:::
|
174
|
+
|
175
|
+
访问 `http://localhost:8080/remote`,可以看到页面中已经包含了生产者的远程模块 `Button` 组件。
|
176
|
+
|
177
|
+
上述用例可以参考:[Modern.js & Module Federation 基础用法示例](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/module-federation/base)。
|
178
|
+
|
179
|
+
## 相关文档
|
180
|
+
|
181
|
+
- [Module Federation 官方文档](https://module-federation.io/zh/guide/framework/modernjs.html)
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
Modern.js 拥有自己的框架插件系统,你可以通过在 `modern.config.ts` 中配置 [`plugins`](/configure/app/plugins) 字段来使用 Modern.js 插件。
|
8
8
|
|
9
|
-
### 插件类型
|
9
|
+
### 插件类型
|
10
10
|
|
11
11
|
框架插件可以细分成三类,分别是:
|
12
12
|
|
@@ -62,8 +62,8 @@ Modern.js 从 `MAJOR_VERSION.46.0` 起开始将底层的构建工具升级为 [R
|
|
62
62
|
| [CSS Minimizer 插件](https://github.com/rspack-contrib/rsbuild-plugin-css-minimizer) | 用于自定义 CSS 压缩工具,切换到 [cssnano](https://cssnano.co/) 或其他工具进行 CSS 压缩。 | [tools.minifyCss](/configure/app/tools/minify-css.html) |
|
63
63
|
| [Pug 插件](https://github.com/rspack-contrib/rsbuild-plugin-pug) | 提供对 Pug 模板引擎的支持 | [tools.pug](/configure/app/tools/pug.html) |
|
64
64
|
| [Rem 插件](https://github.com/rspack-contrib/rsbuild-plugin-rem) | 用于实现移动端页面的 rem 自适应布局 | [output.convertToRem](/configure/app/output/convert-to-rem.html) |
|
65
|
-
| [YAML 插件](https://github.com/rspack-contrib/rsbuild-plugin-yaml) | 用于引用 YAML 文件,并将其转换为 JavaScript 对象 | [
|
66
|
-
| [TOML 插件](https://github.com/rspack-contrib/rsbuild-plugin-toml) | 用于引用 TOML 文件,并将其转换为 JavaScript 对象 | [
|
65
|
+
| [YAML 插件](https://github.com/rspack-contrib/rsbuild-plugin-yaml) | 用于引用 YAML 文件,并将其转换为 JavaScript 对象 | [YAML 文件](/guides/basic-features/static-assets/json-files.html#yaml-文件) |
|
66
|
+
| [TOML 插件](https://github.com/rspack-contrib/rsbuild-plugin-toml) | 用于引用 TOML 文件,并将其转换为 JavaScript 对象 | [TOML 文件](/guides/basic-features/static-assets/json-files.html#toml-文件) |
|
67
67
|
|
68
68
|
#### 未内置的插件
|
69
69
|
|
@@ -75,4 +75,4 @@ Modern.js 从 `MAJOR_VERSION.46.0` 起开始将底层的构建工具升级为 [R
|
|
75
75
|
|
76
76
|
import OtherPlugins from '@site-docs/components/other-plugins.mdx';
|
77
77
|
|
78
|
-
<OtherPlugins />
|
78
|
+
<OtherPlugins />
|
package/i18n.json
CHANGED
package/package.json
CHANGED
@@ -15,17 +15,17 @@
|
|
15
15
|
"modern",
|
16
16
|
"modern.js"
|
17
17
|
],
|
18
|
-
"version": "2.60.
|
18
|
+
"version": "2.60.3",
|
19
19
|
"publishConfig": {
|
20
20
|
"registry": "https://registry.npmjs.org/",
|
21
21
|
"access": "public",
|
22
22
|
"provenance": true
|
23
23
|
},
|
24
24
|
"dependencies": {
|
25
|
-
"@modern-js/sandpack-react": "2.60.
|
25
|
+
"@modern-js/sandpack-react": "2.60.3"
|
26
26
|
},
|
27
27
|
"devDependencies": {
|
28
|
-
"@rspress/shared": "1.31.
|
28
|
+
"@rspress/shared": "1.31.1",
|
29
29
|
"@types/fs-extra": "9.0.13",
|
30
30
|
"@types/node": "^16",
|
31
31
|
"classnames": "^2",
|
@@ -33,7 +33,7 @@
|
|
33
33
|
"fs-extra": "^10",
|
34
34
|
"react": "^18",
|
35
35
|
"react-dom": "^18",
|
36
|
-
"rspress": "1.31.
|
36
|
+
"rspress": "1.31.1",
|
37
37
|
"ts-node": "^10.9.1",
|
38
38
|
"typescript": "^5"
|
39
39
|
},
|