@modern-js/main-doc 2.67.5 → 2.67.6
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/hooks/server/server.mdx +10 -0
- package/docs/en/apis/app/hooks/src/routes.mdx +3 -3
- package/docs/en/apis/app/runtime/bff/use-hono-context.mdx +30 -0
- package/docs/en/components/enable-bff.mdx +1 -27
- package/docs/en/components/rsbuild-config-tooltip.mdx +2 -2
- package/docs/en/components/tech-stack-node-framework.mdx +1 -1
- package/docs/en/configure/app/dev/asset-prefix.mdx +2 -3
- package/docs/en/configure/app/dev/client.mdx +2 -3
- package/docs/en/configure/app/dev/hmr.mdx +2 -3
- package/docs/en/configure/app/dev/live-reload.mdx +2 -3
- package/docs/en/configure/app/dev/progress-bar.mdx +2 -3
- package/docs/en/configure/app/dev/setup-middlewares.mdx +2 -3
- package/docs/en/configure/app/dev/watch-files.mdx +2 -3
- package/docs/en/configure/app/dev/write-to-disk.mdx +2 -3
- package/docs/en/configure/app/html/app-icon.mdx +2 -3
- package/docs/en/configure/app/html/crossorigin.mdx +2 -3
- package/docs/en/configure/app/html/favicon.mdx +2 -3
- package/docs/en/configure/app/html/inject.mdx +2 -3
- package/docs/en/configure/app/html/meta.mdx +2 -3
- package/docs/en/configure/app/html/mount-id.mdx +2 -3
- package/docs/en/configure/app/html/output-structure.mdx +2 -3
- package/docs/en/configure/app/html/script-loading.mdx +2 -3
- package/docs/en/configure/app/html/tags.mdx +2 -3
- package/docs/en/configure/app/html/template-parameters.mdx +2 -3
- package/docs/en/configure/app/html/template.mdx +2 -3
- package/docs/en/configure/app/html/title.mdx +2 -3
- package/docs/en/configure/app/output/asset-prefix.mdx +2 -3
- package/docs/en/configure/app/output/charset.mdx +2 -3
- package/docs/en/configure/app/output/copy.mdx +2 -3
- package/docs/en/configure/app/output/css-modules.mdx +2 -3
- package/docs/en/configure/app/output/data-uri-limit.mdx +2 -3
- package/docs/en/configure/app/output/dist-path.mdx +2 -4
- package/docs/en/configure/app/output/externals.mdx +2 -3
- package/docs/en/configure/app/output/filename-hash.mdx +2 -3
- package/docs/en/configure/app/output/filename.mdx +2 -3
- package/docs/en/configure/app/output/inject-styles.mdx +2 -3
- package/docs/en/configure/app/output/inline-scripts.mdx +2 -3
- package/docs/en/configure/app/output/inline-styles.mdx +2 -3
- package/docs/en/configure/app/output/legal-comments.mdx +2 -3
- package/docs/en/configure/app/output/minify.mdx +2 -3
- package/docs/en/configure/app/output/override-browserslist.mdx +2 -3
- package/docs/en/configure/app/output/polyfill.mdx +2 -3
- package/docs/en/configure/app/output/source-map.mdx +2 -3
- package/docs/en/configure/app/performance/build-cache.mdx +2 -3
- package/docs/en/configure/app/performance/bundle-analyze.mdx +2 -3
- package/docs/en/configure/app/performance/chunk-split.mdx +2 -3
- package/docs/en/configure/app/performance/dns-prefetch.mdx +2 -3
- package/docs/en/configure/app/performance/preconnect.mdx +2 -3
- package/docs/en/configure/app/performance/prefetch.mdx +2 -3
- package/docs/en/configure/app/performance/preload.mdx +2 -3
- package/docs/en/configure/app/performance/print-file-size.mdx +2 -3
- package/docs/en/configure/app/performance/profile.mdx +2 -3
- package/docs/en/configure/app/performance/remove-console.mdx +2 -3
- package/docs/en/configure/app/performance/remove-moment-locale.mdx +2 -3
- package/docs/en/configure/app/security/nonce.mdx +2 -3
- package/docs/en/configure/app/security/sri.mdx +0 -1
- package/docs/en/configure/app/server/port.mdx +2 -3
- package/docs/en/configure/app/source/alias-strategy.mdx +2 -3
- package/docs/en/configure/app/source/alias.mdx +2 -3
- package/docs/en/configure/app/source/decorators.mdx +2 -3
- package/docs/en/configure/app/source/define.mdx +2 -3
- package/docs/en/configure/app/source/exclude.mdx +2 -3
- package/docs/en/configure/app/source/include.mdx +2 -3
- package/docs/en/configure/app/source/pre-entry.mdx +2 -3
- package/docs/en/configure/app/source/transform-import.mdx +2 -3
- package/docs/en/configure/app/tools/css-extract.mdx +2 -3
- package/docs/en/configure/app/tools/css-loader.mdx +2 -2
- package/docs/en/configure/app/tools/html-plugin.mdx +7 -3
- package/docs/en/configure/app/tools/lightningcss-loader.mdx +2 -3
- package/docs/en/configure/app/tools/postcss.mdx +2 -3
- package/docs/en/configure/app/tools/rspack.mdx +2 -3
- package/docs/en/configure/app/tools/style-loader.mdx +2 -3
- package/docs/en/configure/app/tools/swc.mdx +1 -1
- package/docs/en/guides/advanced-features/_meta.json +0 -1
- package/docs/en/guides/advanced-features/bff/extend-server.mdx +33 -82
- package/docs/en/guides/advanced-features/bff/frameworks.mdx +12 -68
- package/docs/en/guides/advanced-features/page-performance/_meta.json +1 -1
- package/docs/en/guides/advanced-features/page-performance/react-compiler.mdx +44 -0
- package/docs/en/guides/advanced-features/web-server.mdx +211 -20
- package/docs/en/guides/basic-features/deploy.mdx +3 -3
- package/docs/en/guides/basic-features/output-files.mdx +0 -28
- package/docs/en/tutorials/first-app/c04-routes.mdx +4 -2
- package/docs/en/tutorials/first-app/c05-loader.mdx +4 -1
- package/docs/zh/apis/app/hooks/server/server.mdx +10 -0
- package/docs/zh/apis/app/hooks/src/routes.mdx +3 -3
- package/docs/zh/apis/app/runtime/bff/use-hono-context.mdx +31 -0
- package/docs/zh/components/enable-bff.mdx +2 -27
- package/docs/zh/components/rsbuild-config-tooltip.mdx +2 -2
- package/docs/zh/components/tech-stack-node-framework.mdx +1 -1
- package/docs/zh/configure/app/dev/asset-prefix.mdx +2 -3
- package/docs/zh/configure/app/dev/client.mdx +2 -3
- package/docs/zh/configure/app/dev/hmr.mdx +2 -3
- package/docs/zh/configure/app/dev/live-reload.mdx +2 -3
- package/docs/zh/configure/app/dev/progress-bar.mdx +2 -3
- package/docs/zh/configure/app/dev/setup-middlewares.mdx +2 -3
- package/docs/zh/configure/app/dev/watch-files.mdx +2 -3
- package/docs/zh/configure/app/dev/write-to-disk.mdx +2 -3
- package/docs/zh/configure/app/html/app-icon.mdx +2 -3
- package/docs/zh/configure/app/html/crossorigin.mdx +2 -3
- package/docs/zh/configure/app/html/favicon.mdx +2 -3
- package/docs/zh/configure/app/html/inject.mdx +2 -3
- package/docs/zh/configure/app/html/meta.mdx +2 -3
- package/docs/zh/configure/app/html/mount-id.mdx +2 -3
- package/docs/zh/configure/app/html/output-structure.mdx +2 -3
- package/docs/zh/configure/app/html/script-loading.mdx +2 -3
- package/docs/zh/configure/app/html/tags.mdx +2 -3
- package/docs/zh/configure/app/html/template-parameters.mdx +2 -3
- package/docs/zh/configure/app/html/template.mdx +2 -3
- package/docs/zh/configure/app/html/title.mdx +2 -3
- package/docs/zh/configure/app/output/asset-prefix.mdx +2 -3
- package/docs/zh/configure/app/output/charset.mdx +2 -3
- package/docs/zh/configure/app/output/copy.mdx +2 -3
- package/docs/zh/configure/app/output/css-modules.mdx +2 -3
- package/docs/zh/configure/app/output/data-uri-limit.mdx +2 -3
- package/docs/zh/configure/app/output/dist-path.mdx +2 -4
- package/docs/zh/configure/app/output/externals.mdx +2 -3
- package/docs/zh/configure/app/output/filename-hash.mdx +2 -3
- package/docs/zh/configure/app/output/filename.mdx +2 -3
- package/docs/zh/configure/app/output/inject-styles.mdx +2 -3
- package/docs/zh/configure/app/output/inline-scripts.mdx +2 -3
- package/docs/zh/configure/app/output/inline-styles.mdx +2 -3
- package/docs/zh/configure/app/output/legal-comments.mdx +2 -3
- package/docs/zh/configure/app/output/minify.mdx +2 -3
- package/docs/zh/configure/app/output/override-browserslist.mdx +2 -3
- package/docs/zh/configure/app/output/polyfill.mdx +2 -3
- package/docs/zh/configure/app/output/source-map.mdx +2 -3
- package/docs/zh/configure/app/performance/build-cache.mdx +2 -3
- package/docs/zh/configure/app/performance/bundle-analyze.mdx +2 -3
- package/docs/zh/configure/app/performance/chunk-split.mdx +2 -3
- package/docs/zh/configure/app/performance/dns-prefetch.mdx +2 -3
- package/docs/zh/configure/app/performance/preconnect.mdx +2 -3
- package/docs/zh/configure/app/performance/prefetch.mdx +2 -3
- package/docs/zh/configure/app/performance/preload.mdx +2 -3
- package/docs/zh/configure/app/performance/print-file-size.mdx +2 -3
- package/docs/zh/configure/app/performance/profile.mdx +2 -3
- package/docs/zh/configure/app/performance/remove-console.mdx +2 -3
- package/docs/zh/configure/app/performance/remove-moment-locale.mdx +2 -3
- package/docs/zh/configure/app/security/nonce.mdx +2 -3
- package/docs/zh/configure/app/security/sri.mdx +0 -1
- package/docs/zh/configure/app/server/port.mdx +2 -3
- package/docs/zh/configure/app/source/alias-strategy.mdx +2 -3
- package/docs/zh/configure/app/source/alias.mdx +2 -3
- package/docs/zh/configure/app/source/decorators.mdx +2 -3
- package/docs/zh/configure/app/source/define.mdx +2 -3
- package/docs/zh/configure/app/source/exclude.mdx +2 -3
- package/docs/zh/configure/app/source/include.mdx +2 -3
- package/docs/zh/configure/app/source/pre-entry.mdx +2 -3
- package/docs/zh/configure/app/source/transform-import.mdx +2 -3
- package/docs/zh/configure/app/tools/css-extract.mdx +2 -3
- package/docs/zh/configure/app/tools/css-loader.mdx +2 -3
- package/docs/zh/configure/app/tools/html-plugin.mdx +6 -3
- package/docs/zh/configure/app/tools/lightningcss-loader.mdx +2 -3
- package/docs/zh/configure/app/tools/postcss.mdx +2 -3
- package/docs/zh/configure/app/tools/rspack.mdx +2 -3
- package/docs/zh/configure/app/tools/style-loader.mdx +2 -3
- package/docs/zh/configure/app/tools/swc.mdx +1 -1
- package/docs/zh/guides/advanced-features/_meta.json +0 -1
- package/docs/zh/guides/advanced-features/bff/extend-server.mdx +28 -76
- package/docs/zh/guides/advanced-features/bff/frameworks.mdx +6 -66
- package/docs/zh/guides/advanced-features/page-performance/_meta.json +1 -1
- package/docs/zh/guides/advanced-features/page-performance/react-compiler.mdx +44 -0
- package/docs/zh/guides/advanced-features/web-server.mdx +209 -25
- package/docs/zh/guides/basic-features/deploy.mdx +4 -3
- package/docs/zh/guides/basic-features/output-files.mdx +0 -28
- package/docs/zh/tutorials/first-app/c04-routes.mdx +4 -2
- package/docs/zh/tutorials/first-app/c05-loader.mdx +4 -1
- package/package.json +7 -4
- package/rspress.config.ts +16 -1
- package/src/components/RsbuildLink/index.tsx +2 -2
- package/src/index.ts +1 -5
- package/src/pages/index.tsx +3 -3
- package/docs/en/apis/app/hooks/api/middleware.mdx +0 -11
- package/docs/en/apis/app/runtime/bff/hook.mdx +0 -44
- package/docs/en/apis/app/runtime/bff/use-context.mdx +0 -38
- package/docs/en/configure/app/bff/enable-handle-web.mdx +0 -24
- package/docs/en/guides/advanced-features/custom-server.mdx +0 -218
- package/docs/zh/apis/app/hooks/api/middleware.mdx +0 -11
- package/docs/zh/apis/app/runtime/bff/hook.mdx +0 -44
- package/docs/zh/apis/app/runtime/bff/use-context.mdx +0 -38
- package/docs/zh/configure/app/bff/enable-handle-web.mdx +0 -24
- package/docs/zh/guides/advanced-features/custom-server.mdx +0 -216
@@ -2,31 +2,39 @@
|
|
2
2
|
|
3
3
|
部分应用中,开发者可能希望对所有 BFF 函数做统一的处理,例如鉴权、日志、数据处理等。
|
4
4
|
|
5
|
-
Modern.js
|
5
|
+
Modern.js 支持用户通过 [Middleware](/guides/advanced-features/web-server.html#middleware) 的方式来自由扩展 BFF Server。
|
6
6
|
|
7
|
-
## 中间件
|
8
7
|
|
9
|
-
|
8
|
+
## 使用中间件
|
10
9
|
|
11
|
-
|
12
|
-
import { hook } from '@modern-js/runtime/server';
|
13
|
-
import { Request, Response, NextFunction } from 'express';
|
10
|
+
开发者可以在 `server/modern.server.ts` 中通过 配置 middlewares 来使用中间件。下面介绍如何手写一个 BFF 中间件,添加权限校验:
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
12
|
+
|
13
|
+
```ts title="server/modern.server.ts"
|
14
|
+
import {
|
15
|
+
type MiddlewareHandler,
|
16
|
+
defineServerConfig,
|
17
|
+
} from '@modern-js/server-runtime';
|
18
|
+
|
19
|
+
const requireAuthForApi: MiddlewareHandler = async (c, next) => {
|
20
|
+
if (c.req.path.startsWith('/api') && c.req.path !== '/api/login') {
|
21
|
+
const sid = c.req.cookie('sid');
|
22
|
+
if (!sid) {
|
23
|
+
return c.json({ code: -1, message: 'need login' }, 400);
|
27
24
|
}
|
28
|
-
}
|
25
|
+
}
|
26
|
+
await next();
|
27
|
+
};
|
28
|
+
|
29
|
+
export default defineServerConfig({
|
30
|
+
middlewares: [
|
31
|
+
{
|
32
|
+
name: 'require-auth-for-api',
|
33
|
+
handler: requireAuthForApi,
|
34
|
+
},
|
35
|
+
]
|
29
36
|
});
|
37
|
+
|
30
38
|
```
|
31
39
|
|
32
40
|
|
@@ -97,60 +105,4 @@ export default () => {
|
|
97
105
|
|
98
106
|

|
99
107
|
|
100
|
-
以上代码模拟了在
|
101
|
-
|
102
|
-
:::info
|
103
|
-
不同运行时框架中,中间件的写法不一定相同,详情可见[运行时框架](/guides/advanced-features/bff/frameworks)。
|
104
|
-
|
105
|
-
:::
|
106
|
-
|
107
|
-
## 定义 Server 实例
|
108
|
-
|
109
|
-
除了中间件之外,还可以通过 `api/app.ts` 文件来定义 BFF Server 的实例。开发者需要默认导出一个能被运行时框架插件识别的实例。这里简单展示一下 Koa 和 Express 如何定义 Server 实例。
|
110
|
-
|
111
|
-
import { Tabs, Tab as TabItem } from "@theme";
|
112
|
-
|
113
|
-
<Tabs>
|
114
|
-
<TabItem value="express" label="Express.js" default>
|
115
|
-
|
116
|
-
```ts title="api/app.ts"
|
117
|
-
import express from 'express';
|
118
|
-
|
119
|
-
const app = express();
|
120
|
-
app.use(async (req, res, next) => {
|
121
|
-
console.info(`access url: ${req.url}`);
|
122
|
-
next();
|
123
|
-
});
|
124
|
-
|
125
|
-
export default app;
|
126
|
-
```
|
127
|
-
|
128
|
-
</TabItem>
|
129
|
-
<TabItem value="koa" label="Koa.js">
|
130
|
-
|
131
|
-
```ts title="api/app.ts"
|
132
|
-
import koa from 'koa';
|
133
|
-
|
134
|
-
const app = new Koa();
|
135
|
-
app.use(async (ctx, next) => {
|
136
|
-
console.info(`access url: ${ctx.url}`);
|
137
|
-
await next();
|
138
|
-
});
|
139
|
-
|
140
|
-
export default app;
|
141
|
-
```
|
142
|
-
|
143
|
-
</TabItem>
|
144
|
-
</Tabs>
|
145
|
-
|
146
|
-
在复杂的 BFF 逻辑中,定义 Server 实例可以更方便通过一个入口来组织代码逻辑,设计目录结构。在这个文件中,可以执行初始化逻辑,添加全局中间件,声明路由,甚至扩展原有框架。
|
147
|
-
|
148
|
-
BFF 函数定义的路由会在 `app.ts` 文件定义的路由之后注册,所以在这里你也可以拦截 BFF 函数定义的路由,进行预处理或是提前响应。
|
149
|
-
|
150
|
-
:::note
|
151
|
-
此时,如果应用中同时存在 `api/_app.ts`,则定义的中间件会被放在 `api/app.ts` 导出实例的最后执行。多数情况下,中间件就能覆盖大多数 BFF 函数的定制需求。只有当应用的服务端逻辑比较复杂时,才需要自定义 Server 实例。
|
152
|
-
:::
|
153
|
-
|
154
|
-
:::caution
|
155
|
-
当应用中没有 `api/app.ts` 的时候,Modern.js 默认会添加 [koa-body](https://www.npmjs.com/package/koa-body)。当应用中存在 `api/app.ts` 时,如果开发者希望使用带有 Body 的 BFF 函数,需要**自行添加** `koa-body`。
|
156
|
-
:::
|
108
|
+
以上代码模拟了在 `server/Modern.server.ts` 中定义中间件的方式,实现了简易的登录功能。同样,可以在这个配置文件中实现其他功能来扩展 BFF Server。
|
@@ -5,82 +5,22 @@ title: 运行时框架
|
|
5
5
|
|
6
6
|
# 运行时框架
|
7
7
|
|
8
|
-
Modern.js
|
9
|
-
|
10
|
-
使用不同运行时框架时,有部分 API 会存在差异。
|
8
|
+
Modern.js 以 [Hono.js](https://hono.dev/) 作为 BFF 和 Server 运行时框架,因此可以基于 Hono.js 生态[扩展 BFF Server](/guides/advanced-features/bff/extend-server.html)。
|
11
9
|
|
12
10
|
## 获取请求上下文
|
13
11
|
|
14
|
-
在 BFF
|
15
|
-
|
16
|
-
import { Tabs, Tab as TabItem } from "@theme";
|
17
|
-
|
18
|
-
<Tabs>
|
19
|
-
<TabItem value="express" label="Express.js" default>
|
20
|
-
|
21
|
-
```ts title="api/lambda/hello.ts"
|
22
|
-
import { useContext } from '@modern-js/runtime/express'
|
23
|
-
export const get = async () => {
|
24
|
-
const { req } = useContext();
|
25
|
-
console.info(`access url: ${req.url}`);
|
26
|
-
return 'Hello Modern.js'
|
27
|
-
};
|
28
|
-
```
|
29
|
-
|
30
|
-
</TabItem>
|
31
|
-
<TabItem value="koa" label="Koa.js">
|
12
|
+
在 BFF 函数中,有时需要获取请求上下文,来处理更多逻辑。此时,你可以通过 `useHonoContext` 来获取:
|
32
13
|
|
33
14
|
```ts title="api/lambda/hello.ts"
|
34
|
-
import {
|
15
|
+
import { useHonoContext } from '@modern-js/plugin-bff/hono'
|
35
16
|
export const get = async () => {
|
36
|
-
const
|
37
|
-
console.info(`access url: ${req.url}`);
|
17
|
+
const c = useHonoContext();
|
18
|
+
console.info(`access url: ${c.req.url}`);
|
38
19
|
return 'Hello Modern.js'
|
39
20
|
};
|
40
21
|
```
|
41
22
|
|
42
|
-
</TabItem>
|
43
|
-
</Tabs>
|
44
|
-
|
45
23
|
:::info
|
46
|
-
详细内容可以参考 [
|
24
|
+
详细内容可以参考 [useHonoContext](/apis/app/runtime/bff/use-hono-context)。
|
47
25
|
:::
|
48
26
|
|
49
|
-
## 使用中间件
|
50
|
-
|
51
|
-
在 BFF 函数中,有时需要使用中间件,来处理更多逻辑。此时,根据不同的运行时框架,你需要从通过不同的 API 来获取:
|
52
|
-
|
53
|
-
<Tabs>
|
54
|
-
<TabItem value="express" label="Express.js" default>
|
55
|
-
|
56
|
-
```ts title="api/_app.ts"
|
57
|
-
import { hook } from '@modern-js/runtime/express';
|
58
|
-
|
59
|
-
export default hook(({ addMiddleware }) => {
|
60
|
-
addMiddleware((req, res, next) => {
|
61
|
-
req.query.id = 'koa';
|
62
|
-
next();
|
63
|
-
});
|
64
|
-
});
|
65
|
-
```
|
66
|
-
|
67
|
-
</TabItem>
|
68
|
-
<TabItem value="koa" label="Koa.js">
|
69
|
-
|
70
|
-
```ts title="api/_app.ts"
|
71
|
-
import { hook } from '@modern-js/runtime/koa';
|
72
|
-
|
73
|
-
export default hook(({ addMiddleware }) => {
|
74
|
-
addMiddleware(async (ctx, next) => {
|
75
|
-
ctx.req.query.id = 'koa';
|
76
|
-
await next();
|
77
|
-
});
|
78
|
-
});
|
79
|
-
```
|
80
|
-
|
81
|
-
</TabItem>
|
82
|
-
</Tabs>
|
83
|
-
|
84
|
-
:::info
|
85
|
-
详细内容可以参考 [hook](/apis/app/runtime/bff/hook)。
|
86
|
-
:::
|
@@ -1 +1 @@
|
|
1
|
-
["code-split", "inline-assets", "optimize-bundle"]
|
1
|
+
["code-split", "inline-assets", "optimize-bundle", "react-compiler"]
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# React Compiler
|
2
|
+
|
3
|
+
React Compiler 是 React 19 引入的一个实验性编译器,它可以自动优化你的 React 代码。
|
4
|
+
|
5
|
+
在开始使用 React Compiler 之前,建议阅读 [React Compiler 文档](https://zh-hans.react.dev/learn/react-compiler),以了解 React Compiler 的功能、当前状态和使用方法。
|
6
|
+
|
7
|
+
## 如何使用
|
8
|
+
|
9
|
+
在 Modern.js 中使用 React Compiler 的步骤如下:
|
10
|
+
|
11
|
+
1. Modern.js 目前项目还未正式支持 React 19,可以在 React 17 或 18 项目中安装 `react-compiler-runtime@rc`,以允许编译后的代码在 19 之前的版本上运行。
|
12
|
+
|
13
|
+
2. 目前 React Compiler 仅提供了 Babel 插件,你需要安装 `babel-plugin-react-compiler`。
|
14
|
+
|
15
|
+
3. 在你的 Modern.js 配置文件中注册 Babel 插件:
|
16
|
+
|
17
|
+
```ts title="modern.config.ts"
|
18
|
+
import { appTools, defineConfig } from '@modern-js/app-tools';
|
19
|
+
|
20
|
+
export default defineConfig({
|
21
|
+
runtime: {
|
22
|
+
router: true,
|
23
|
+
},
|
24
|
+
tools: {
|
25
|
+
babel(_, { addPlugins }) {
|
26
|
+
addPlugins([
|
27
|
+
[
|
28
|
+
'babel-plugin-react-compiler',
|
29
|
+
{
|
30
|
+
target: '18',
|
31
|
+
},
|
32
|
+
],
|
33
|
+
]);
|
34
|
+
},
|
35
|
+
},
|
36
|
+
plugins: [
|
37
|
+
appTools({
|
38
|
+
bundler: 'rspack',
|
39
|
+
}),
|
40
|
+
],
|
41
|
+
});
|
42
|
+
```
|
43
|
+
|
44
|
+
> 详细代码可以参考:[Modern.js & React Compiler 示例项目](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/react-compiler)
|
@@ -2,42 +2,230 @@
|
|
2
2
|
sidebar_position: 16
|
3
3
|
---
|
4
4
|
|
5
|
-
# 自定义 Web Server
|
5
|
+
# 自定义 Web Server
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
Modern.js 将大部分项目需要的服务端能力都进行了封装,通常项目无需进行服务端开发。但在有些开发场景下,例如用户鉴权、请求预处理、添加页面渲染骨架等,项目仍需要对服务端进行定制。
|
8
|
+
|
9
|
+
## 开启自定义 Web Server
|
10
|
+
|
11
|
+
:::info
|
12
|
+
必须确保 Modern.js 版本是 x.67.5 及以上。
|
9
13
|
:::
|
10
14
|
|
11
|
-
|
15
|
+
开启自定义 Web Server 功能,需要执行以下步骤:
|
16
|
+
1. devDependencies 增加 `@modern-js/server-runtime` 及 `ts-node`依赖并安装。
|
17
|
+
2. `tsconfig` 的 `include` 中添加 `server`。
|
18
|
+
3. 项目目录下创建 `server/modern.server.ts` 文件,可以在这个文件中编写自定义逻辑。
|
19
|
+
|
20
|
+
## 自定义 Web Server 能力
|
21
|
+
|
22
|
+
`server/modern.server.ts` 文件中添加如下配置来扩展 Server:
|
23
|
+
- **中间件(Middleware)**
|
24
|
+
- **渲染中间件(RenderMiddleware)**
|
25
|
+
- **服务端插件(Plugin)**
|
12
26
|
|
13
|
-
|
27
|
+
其中 **Plugin** 中可以定义 **Middleware** 与 **RenderMiddleware**。 中间件加载流程如下图所示:
|
28
|
+
|
29
|
+
<img
|
30
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/10eh7nuhpenuhog/server-md-wf.png"
|
31
|
+
style={{ width: '100%', maxWidth: '540px' }}
|
32
|
+
/>
|
33
|
+
|
34
|
+
### 基本配置
|
35
|
+
|
36
|
+
```ts title="server/modern.server.ts"
|
37
|
+
import { defineServerConfig } from '@modern-js/server-runtime';
|
38
|
+
|
39
|
+
export default defineServerConfig({
|
40
|
+
middlewares: [], // 中间件
|
41
|
+
renderMiddlewares: [], // 渲染中间件
|
42
|
+
plugins: [], // 插件
|
43
|
+
});
|
44
|
+
```
|
45
|
+
|
46
|
+
|
47
|
+
### 类型定义
|
48
|
+
|
49
|
+
`defineServerConfig` 类型定义如下:
|
50
|
+
|
51
|
+
```ts
|
52
|
+
import type { MiddlewareHandler } from 'hono';
|
53
|
+
|
54
|
+
type MiddlewareObj = {
|
55
|
+
name: string;
|
56
|
+
path?: string;
|
57
|
+
method?: 'options' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'all';
|
58
|
+
handler: MiddlewareHandler | MiddlewareHandler[];
|
59
|
+
};
|
60
|
+
type ServerConfig = {
|
61
|
+
middlewares?: MiddlewareObj[];
|
62
|
+
renderMiddlewares?: MiddlewareObj[];
|
63
|
+
plugins?: (ServerPlugin | ServerPluginLegacy)[];
|
64
|
+
}
|
65
|
+
```
|
66
|
+
|
67
|
+
|
68
|
+
### Middleware
|
69
|
+
|
70
|
+
Middleware 支持在 Modern.js 服务的**请求处理**与**页面路由**的流程前后,执行自定义逻辑。
|
71
|
+
即自定义逻辑既要处理接口路由,也要作用于页面路由,那么 Middleware 是不二选择。
|
14
72
|
|
15
73
|
:::note
|
16
|
-
|
74
|
+
如果仅需要处理 BFF 接口路由,可以通过检查 `req.path` 是否以 BFF `prefix` 开头,来判断是否为 BFF 接口请求。
|
17
75
|
:::
|
18
76
|
|
19
|
-
|
77
|
+
使用姿势如下:
|
20
78
|
|
21
|
-
|
79
|
+
```ts title="server/modern.server.ts"
|
80
|
+
import { defineServerConfig, type MiddlewareHandler } from '@modern-js/server-runtime';
|
81
|
+
|
82
|
+
export const handler: MiddlewareHandler = async (c, next) => {
|
83
|
+
const monitors = c.get('monitors');
|
84
|
+
const start = Date.now();
|
22
85
|
|
23
|
-
|
24
|
-
|
25
|
-
|
86
|
+
await next();
|
87
|
+
|
88
|
+
const end = Date.now();
|
89
|
+
// 上报耗时
|
90
|
+
monitors.timing('request_timing', end - start);
|
91
|
+
};
|
92
|
+
|
93
|
+
export default defineServerConfig({
|
94
|
+
middlewares: [
|
95
|
+
{
|
96
|
+
name: 'request-timing',
|
97
|
+
handler,
|
98
|
+
},
|
99
|
+
],
|
100
|
+
});
|
26
101
|
```
|
27
102
|
|
28
|
-
|
103
|
+
:::warning
|
104
|
+
必须执行 `next` 函数才会执行后续的 Middleware。
|
105
|
+
:::
|
106
|
+
|
29
107
|
|
30
|
-
|
31
|
-
import { serverPlugin } from '@modern-js/plugin-server';
|
108
|
+
### RenderMiddleware
|
32
109
|
|
33
|
-
|
34
|
-
|
110
|
+
如果只需要处理页面渲染的前后执行逻辑,modern.js 也提供了渲染中间件,使用姿势如下:
|
111
|
+
|
112
|
+
```ts title="server/modern.server.ts"
|
113
|
+
import { defineServerConfig, type MiddlewareHandler } from '@modern-js/server-runtime';
|
114
|
+
|
115
|
+
// 注入 render 性能指标
|
116
|
+
const renderTiming: MiddlewareHandler = async (c, next) => {
|
117
|
+
const start = Date.now();
|
118
|
+
|
119
|
+
await next();
|
120
|
+
|
121
|
+
const end = Date.now();
|
122
|
+
c.res.headers.set('server-timing', `render; dur=${end - start}`);
|
123
|
+
};
|
124
|
+
|
125
|
+
// 修改响应体
|
126
|
+
const modifyResBody: MiddlewareHandler = async (c, next) => {
|
127
|
+
await next();
|
128
|
+
|
129
|
+
const { res } = c;
|
130
|
+
const text = await res.text();
|
131
|
+
const newText = text.replace('<body>', '<body> <h3>bytedance</h3>');
|
132
|
+
|
133
|
+
c.res = c.body(newText, {
|
134
|
+
status: res.status,
|
135
|
+
headers: res.headers,
|
136
|
+
});
|
137
|
+
};
|
138
|
+
|
139
|
+
export default defineServerConfig({
|
140
|
+
renderMiddlewares: [
|
141
|
+
{
|
142
|
+
name: 'render-timing',
|
143
|
+
handler: renderTiming,
|
144
|
+
},
|
145
|
+
{
|
146
|
+
name: 'modify-res-body',
|
147
|
+
handler: modifyResBody,
|
148
|
+
},
|
149
|
+
],
|
35
150
|
});
|
36
151
|
```
|
37
152
|
|
38
|
-
开启功能后,项目目录下会自动创建 `server/index.ts` 文件,可以在这个文件中编写自定义逻辑。
|
39
153
|
|
40
|
-
|
154
|
+
### Plugin
|
155
|
+
|
156
|
+
Modern.js 支持在自定义插件中为 Server 添加上述 Middleware 及 RenderMiddleware,使用姿势如下:
|
157
|
+
|
158
|
+
|
159
|
+
```ts title="server/plugins/server.ts"
|
160
|
+
import type { ServerPluginLegacy } from '@modern-js/server-runtime';
|
161
|
+
|
162
|
+
export default (): ServerPluginLegacy => ({
|
163
|
+
name: 'serverPlugin',
|
164
|
+
setup(api) {
|
165
|
+
return {
|
166
|
+
prepare(serverConfig) {
|
167
|
+
const { middlewares, renderMiddlewares } = api.useAppContext();
|
168
|
+
|
169
|
+
// 注入服务端数据,供页面 dataLoader 消费
|
170
|
+
middlewares?.push({
|
171
|
+
name: 'server-plugin-middleware',
|
172
|
+
handler: async (c, next) => {
|
173
|
+
c.set('message', 'hi modern.js');
|
174
|
+
await next();
|
175
|
+
// ...
|
176
|
+
},
|
177
|
+
});
|
178
|
+
|
179
|
+
// 重定向
|
180
|
+
renderMiddlewares?.push({
|
181
|
+
name: 'server-plugin-render-middleware',
|
182
|
+
handler: async (c, next) => {
|
183
|
+
const user = getUser(c.req);
|
184
|
+
if (!user) {
|
185
|
+
return c.redirect('/login');
|
186
|
+
}
|
187
|
+
|
188
|
+
await next();
|
189
|
+
},
|
190
|
+
});
|
191
|
+
return serverConfig;
|
192
|
+
},
|
193
|
+
};
|
194
|
+
},
|
195
|
+
});
|
196
|
+
```
|
197
|
+
|
198
|
+
|
199
|
+
```ts title="server/modern.server.ts"
|
200
|
+
import { defineServerConfig } from '@modern-js/server-runtime';
|
201
|
+
import serverPlugin from './plugins/serverPlugin';
|
202
|
+
|
203
|
+
export default defineServerConfig({
|
204
|
+
plugins: [serverPlugin()],
|
205
|
+
});
|
206
|
+
```
|
207
|
+
|
208
|
+
|
209
|
+
```ts title="src/routes/page.data.ts"
|
210
|
+
import { useHonoContext } from '@modern-js/server-runtime';
|
211
|
+
import { defer } from '@modern-js/runtime/router';
|
212
|
+
|
213
|
+
export default () => {
|
214
|
+
const ctx = useHonoContext();
|
215
|
+
// SSR 场景消费服务端注入的数据
|
216
|
+
const message = ctx.get('message');
|
217
|
+
|
218
|
+
// ...
|
219
|
+
};
|
220
|
+
|
221
|
+
```
|
222
|
+
|
223
|
+
|
224
|
+
## 旧版 API(废弃)
|
225
|
+
|
226
|
+
:::warning
|
227
|
+
旧版 API 兼容但不再推荐使用,扩展 Server 能力请移步 [自定义 Web Server](/guides/advanced-features/web-server.html),迁移指南参考 [迁移至新版自定义 Web Server](/guides/advanced-features/web-server.html#迁移至新版自定义-web-server)。
|
228
|
+
:::
|
41
229
|
|
42
230
|
### Unstable Middleware
|
43
231
|
|
@@ -68,10 +256,6 @@ export const unstableMiddleware: UnstableMiddleware[] = [time];
|
|
68
256
|
|
69
257
|
### Hook
|
70
258
|
|
71
|
-
:::warning
|
72
|
-
我们推荐使用 UnstableMiddleware 代替 Hook。
|
73
|
-
:::
|
74
|
-
|
75
259
|
Modern.js 提供的 Hook 用于控制 Web Server 中的特定逻辑,所有的页面请求都会经过 Hook。
|
76
260
|
|
77
261
|
目前提供了两种 Hook,分别是 `AfterMatch` 和 `AfterRender`,开发者可以在 `server/index.ts` 中这样写:
|
@@ -102,12 +286,12 @@ export const afterRender: AfterRenderHook = (ctx, next) => {
|
|
102
286
|
:::
|
103
287
|
|
104
288
|
|
105
|
-
## 迁移至新版自定义 Server
|
289
|
+
## 迁移至新版自定义 Web Server
|
106
290
|
|
107
291
|
### 迁移背景
|
108
292
|
|
109
293
|
Modern.js Server 在不断演进,为了提供更强大的功能,我们对中间件和 Server 插件的定义和使用方式进行了优化。
|
110
|
-
|
294
|
+
虽然旧版 API 仍被兼容,但我们强烈建议您按照本指南进行迁移,以充分利用新版的优势。
|
111
295
|
|
112
296
|
### 迁移步骤
|
113
297
|
|
@@ -152,7 +336,7 @@ UnstableMiddleware `Context` 和 Hono `Context` 的具体差异:
|
|
152
336
|
| `c.request` | `c.req.raw` | 参考 [HonoRequest raw](https://hono.dev/docs/api/request#raw) 文档 |
|
153
337
|
| `c.response` | `c.res` | 参考 [Hono Context res](https://hono.dev/docs/api/context#res) 文档 |
|
154
338
|
| `c.route` | `c.get('route')` | 获取应用上下文信息 |
|
155
|
-
| `loaderContext.get` | `honoContext.get` | 通过 `c.set` 注入数据后 dataLoader 中消费:旧版通过 `loaderContext.get` 获取,新版参考 [Plugin](/guides/advanced-features/
|
339
|
+
| `loaderContext.get` | `honoContext.get` | 通过 `c.set` 注入数据后 dataLoader 中消费:旧版通过 `loaderContext.get` 获取,新版参考 [Plugin](/guides/advanced-features/web-server.html#使用姿势-2) 示例 |
|
156
340
|
|
157
341
|
#### Middleware
|
158
342
|
|
@@ -110,7 +110,6 @@ Netlify 是一个流行的 Web 开发平台,专为构建、发布和维护现
|
|
110
110
|
|
111
111
|
:::info
|
112
112
|
你可参考部署[项目示例](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/modern-js-deploy-csr)。
|
113
|
-
|
114
113
|
:::
|
115
114
|
|
116
115
|
在 Netlify 平台上添加项目,部署即可。
|
@@ -197,6 +196,7 @@ Vercel 是一个面向现代 Web 应用的部署平台,它提供了丰富的
|
|
197
196
|
### 纯前端项目
|
198
197
|
|
199
198
|
在当前项目的根目录添加 `vercel.json` 文件:
|
199
|
+
|
200
200
|
```bash
|
201
201
|
./
|
202
202
|
├── src
|
@@ -206,6 +206,7 @@ Vercel 是一个面向现代 Web 应用的部署平台,它提供了丰富的
|
|
206
206
|
```
|
207
207
|
|
208
208
|
在 `vercel.json` 中添加以下内容:
|
209
|
+
|
209
210
|
```json title="vercel.json"
|
210
211
|
{
|
211
212
|
"buildCommand": "modern deploy",
|
@@ -219,7 +220,6 @@ Vercel 是一个面向现代 Web 应用的部署平台,它提供了丰富的
|
|
219
220
|
|
220
221
|
:::info
|
221
222
|
你可参考部署[项目示例](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/modern-js-deploy-csr)。
|
222
|
-
|
223
223
|
:::
|
224
224
|
|
225
225
|
### 全栈项目
|
@@ -314,6 +314,7 @@ Github Pages 支持两种部署方式,通过分支部署或通过 Github Actio
|
|
314
314
|
4. 执行 `npm run deploy:gh-pages`。
|
315
315
|
|
316
316
|
:::info
|
317
|
+
|
317
318
|
1. 执行 `MODERNJS_DEPLOY=ghPages modern deploy`,Modern.js 会把可用于 github 部署的产物构建到 `.output` 目录。
|
318
319
|
2. 可以参考项目[示例](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/modern-js-deploy-csr)。
|
319
320
|
|
@@ -393,7 +394,7 @@ Nginx 是一个高性能的 HTTP 和反向代理服务器,它可以处理静
|
|
393
394
|
|
394
395
|
如果你的项目是纯前端项目,也可以通过 Nginx 来部署应用,以下提供一个 Nginx 配置的示例来演示如何托管一个纯前端项目的产物。
|
395
396
|
|
396
|
-
```
|
397
|
+
```nginx title="nginx.conf"
|
397
398
|
# user [user] [group];
|
398
399
|
worker_processes 1;
|
399
400
|
|
@@ -96,34 +96,6 @@ dist
|
|
96
96
|
└── qux.[hash].mp4
|
97
97
|
```
|
98
98
|
|
99
|
-
## Node.js 产物目录
|
100
|
-
|
101
|
-
当你在 Modern.js 中开启了 SSR 或 SSG 等服务端功能时,Modern.js 会在构建后生成一份 Node.js 产物,并输出到 `bundles` 目录下:
|
102
|
-
|
103
|
-
```bash
|
104
|
-
dist
|
105
|
-
├── bundles
|
106
|
-
│ └── [name].js
|
107
|
-
├── static
|
108
|
-
└── html
|
109
|
-
```
|
110
|
-
|
111
|
-
Node.js 产物通常只包含 JS 文件,不包含 HTML、CSS 等文件。此外,Node 产物的 JS 文件名称也不会自动生成哈希值。
|
112
|
-
|
113
|
-
你可以通过 [output.distPath.server](/configure/app/output/dist-path) 配置项来修改 Node 产物的输出路径。
|
114
|
-
|
115
|
-
比如,将 Node.js 产物输出到 `server` 目录:
|
116
|
-
|
117
|
-
```ts
|
118
|
-
export default {
|
119
|
-
output: {
|
120
|
-
distPath: {
|
121
|
-
server: 'server',
|
122
|
-
},
|
123
|
-
},
|
124
|
-
};
|
125
|
-
```
|
126
|
-
|
127
99
|
## 扁平化产物目录
|
128
100
|
|
129
101
|
有时候你不想产物目录有太多层级,可以将目录设置为空字符串,使生成的产物目录扁平化。
|
@@ -118,8 +118,9 @@ import { Radio } from 'antd';
|
|
118
118
|
|
119
119
|
然后将 UI 最顶部进行修改,增加一组单选框
|
120
120
|
|
121
|
-
```tsx
|
121
|
+
```tsx
|
122
122
|
export default function Layout() {
|
123
|
+
// [!code highlight:8]
|
123
124
|
return (
|
124
125
|
<div>
|
125
126
|
<div className="h-16 p-2 flex items-center justify-center">
|
@@ -146,8 +147,9 @@ import { Outlet, useLocation, useNavigate } from '@modern-js/runtime/router';
|
|
146
147
|
|
147
148
|
最后在 Layout 组件里增加局部状态和相关逻辑:
|
148
149
|
|
149
|
-
```tsx
|
150
|
+
```tsx
|
150
151
|
export default function Layout() {
|
152
|
+
// [!code highlight:8]
|
151
153
|
const navigate = useNavigate();
|
152
154
|
const location = useLocation();
|
153
155
|
const [currentList, setList] = useState(location.pathname || '/');
|
@@ -56,11 +56,13 @@ Data Loader 并非只为 SSR 工作。在 CSR 项目中,Data Loader 也可以
|
|
56
56
|
|
57
57
|
Modern.js 也提供了一个叫 `useLoaderData` 的 hooks API,我们修改 `src/routes/page.tsx` 导出的组件:
|
58
58
|
|
59
|
-
```tsx
|
59
|
+
```tsx
|
60
|
+
// [!code highlight:2]
|
60
61
|
import { useLoaderData } from '@modern-js/runtime/router';
|
61
62
|
import type { LoaderData } from './page.data';
|
62
63
|
|
63
64
|
function Index() {
|
65
|
+
// [!code highlight:1]
|
64
66
|
const { data } = useLoaderData() as LoaderData;
|
65
67
|
|
66
68
|
return (
|
@@ -68,6 +70,7 @@ function Index() {
|
|
68
70
|
<Helmet>
|
69
71
|
<title>All</title>
|
70
72
|
</Helmet>
|
73
|
+
// [!code highlight:1]
|
71
74
|
<List
|
72
75
|
dataSource={data}
|
73
76
|
renderItem={info => <Item key={info.name} info={info} />}
|