@modern-js/main-doc 2.59.0 → 2.60.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/_meta.json +10 -5
- package/docs/en/apis/app/hooks/api/lambda.mdx +4 -48
- package/docs/en/apis/app/hooks/api/middleware.mdx +11 -0
- package/docs/en/community/blog/v2-release-note.mdx +1 -1
- package/docs/en/components/enable-bff.mdx +19 -2
- package/docs/en/components/extend-bff-function.mdx +5 -0
- package/docs/en/components/other-plugins.mdx +0 -0
- package/docs/en/configure/app/auto-load-plugin.mdx +4 -0
- package/docs/en/configure/app/plugins.mdx +2 -2
- package/docs/en/configure/app/tools/esbuild.mdx +1 -1
- package/docs/en/configure/app/tools/swc.mdx +1 -1
- package/docs/en/guides/_meta.json +0 -5
- package/docs/en/guides/advanced-features/_meta.json +7 -4
- package/docs/en/guides/advanced-features/bff/_meta.json +1 -1
- package/docs/en/guides/advanced-features/bff/extend-server.mdx +154 -0
- package/docs/en/guides/advanced-features/bff/frameworks.mdx +52 -123
- package/docs/en/guides/advanced-features/bff/function.mdx +108 -80
- package/docs/en/guides/advanced-features/bff/sdk.mdx +40 -51
- package/docs/en/guides/advanced-features/build-performance.mdx +6 -21
- package/docs/en/guides/advanced-features/page-performance/_meta.json +1 -0
- package/docs/en/guides/basic-features/render/streaming-ssr.mdx +1 -1
- package/docs/en/guides/basic-features/routes.mdx +2 -3
- package/docs/en/guides/basic-features/static-assets.mdx +1 -1
- package/docs/en/guides/deprecated.md +2 -0
- package/docs/en/guides/topic-detail/_meta.json +0 -6
- package/docs/en/plugin/_meta.json +19 -0
- package/docs/en/plugin/cli-plugins/_meta.json +1 -0
- package/docs/en/plugin/cli-plugins/plugin-bff.mdx +5 -0
- package/docs/en/plugin/cli-plugins/plugin-ssg.mdx +5 -0
- package/docs/en/{guides/rsbuild-plugins → plugin/cli-plugins}/plugin-swc.mdx +7 -0
- package/docs/en/plugin/cli-plugins/plugin-tailwind.mdx +5 -0
- package/docs/en/plugin/cli-plugins.mdx +6 -0
- package/docs/en/{guides/advanced-features/rsbuild-plugin.mdx → plugin/introduction.mdx} +34 -9
- package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/extend.mdx +1 -1
- package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/implement.mdx +3 -3
- package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/plugin-api.mdx +2 -2
- package/docs/en/plugin/rsbuild-plugins/_meta.json +1 -0
- package/docs/en/plugin/rsbuild-plugins.mdx +3 -0
- package/docs/zh/_meta.json +10 -5
- package/docs/zh/apis/app/hooks/api/lambda.mdx +5 -48
- package/docs/zh/apis/app/hooks/api/middleware.mdx +11 -0
- package/docs/zh/community/blog/v2-release-note.mdx +1 -1
- package/docs/zh/components/enable-bff.mdx +19 -2
- package/docs/zh/components/extend-bff-function.mdx +5 -0
- package/docs/zh/components/other-plugins.mdx +0 -0
- package/docs/zh/configure/app/auto-load-plugin.mdx +4 -0
- package/docs/zh/configure/app/plugins.mdx +2 -2
- package/docs/zh/configure/app/tools/esbuild.mdx +1 -1
- package/docs/zh/configure/app/tools/swc.mdx +1 -1
- package/docs/zh/guides/_meta.json +0 -5
- package/docs/zh/guides/advanced-features/_meta.json +7 -4
- package/docs/zh/guides/advanced-features/bff/_meta.json +1 -1
- package/docs/zh/guides/advanced-features/bff/extend-server.mdx +156 -0
- package/docs/zh/guides/advanced-features/bff/frameworks.mdx +51 -117
- package/docs/zh/guides/advanced-features/bff/function.mdx +69 -59
- package/docs/zh/guides/advanced-features/bff/sdk.mdx +27 -36
- package/docs/zh/guides/advanced-features/build-performance.mdx +6 -21
- package/docs/zh/guides/advanced-features/page-performance/_meta.json +1 -0
- package/docs/zh/guides/advanced-features/rspack-start.mdx +2 -2
- package/docs/zh/guides/basic-features/alias.mdx +5 -11
- package/docs/zh/guides/basic-features/env-vars.mdx +1 -1
- package/docs/zh/guides/basic-features/routes.mdx +1 -2
- package/docs/zh/guides/basic-features/static-assets.mdx +1 -1
- package/docs/zh/guides/deprecated.md +4 -0
- package/docs/zh/guides/topic-detail/_meta.json +0 -6
- package/docs/zh/plugin/_meta.json +19 -0
- package/docs/zh/plugin/cli-plugins/_meta.json +1 -0
- package/docs/zh/plugin/cli-plugins/plugin-bff.mdx +5 -0
- package/docs/zh/plugin/cli-plugins/plugin-ssg.mdx +5 -0
- package/docs/zh/{guides/rsbuild-plugins → plugin/cli-plugins}/plugin-swc.mdx +7 -0
- package/docs/zh/plugin/cli-plugins/plugin-tailwind.mdx +5 -0
- package/docs/zh/plugin/cli-plugins.mdx +6 -0
- package/docs/zh/{guides/advanced-features/rsbuild-plugin.mdx → plugin/introduction.mdx} +36 -11
- package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/extend.mdx +1 -1
- package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/implement.mdx +3 -3
- package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/plugin-api.mdx +2 -2
- package/docs/zh/plugin/rsbuild-plugins/_meta.json +1 -0
- package/docs/zh/plugin/rsbuild-plugins.mdx +4 -0
- package/i18n.json +27 -3
- package/package.json +5 -4
- package/rspress.config.ts +1 -58
- package/src/components/Footer/index.tsx +1 -1
- package/src/pages/index.tsx +0 -1
- package/docs/en/apis/app/hooks/api/api.mdx +0 -80
- package/docs/en/apis/app/hooks/api/app.mdx +0 -12
- package/docs/en/guides/advanced-features/bff/type.mdx +0 -46
- package/docs/en/guides/advanced-features/eslint.mdx +0 -148
- package/docs/zh/apis/app/hooks/api/api.mdx +0 -81
- package/docs/zh/apis/app/hooks/api/app.mdx +0 -12
- package/docs/zh/guides/advanced-features/bff/type.mdx +0 -46
- package/docs/zh/guides/advanced-features/eslint.mdx +0 -152
- /package/docs/en/guides/advanced-features/{bff/index.mdx → bff.mdx} +0 -0
- /package/docs/en/guides/advanced-features/{code-split.mdx → page-performance/code-split.mdx} +0 -0
- /package/docs/en/guides/advanced-features/{inline-assets.mdx → page-performance/inline-assets.mdx} +0 -0
- /package/docs/en/guides/advanced-features/{optimize-bundle.mdx → page-performance/optimize-bundle.mdx} +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/_meta.json +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook-list.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/introduction.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/lifecycle.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/relationship.mdx +0 -0
- /package/docs/en/{guides → plugin}/rsbuild-plugins/plugin-esbuild.mdx +0 -0
- /package/docs/zh/guides/advanced-features/{bff/index.mdx → bff.mdx} +0 -0
- /package/docs/zh/guides/advanced-features/{code-split.mdx → page-performance/code-split.mdx} +0 -0
- /package/docs/zh/guides/advanced-features/{inline-assets.mdx → page-performance/inline-assets.mdx} +0 -0
- /package/docs/zh/guides/advanced-features/{optimize-bundle.mdx → page-performance/optimize-bundle.mdx} +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/_meta.json +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook-list.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/introduction.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/lifecycle.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/relationship.mdx +0 -0
- /package/docs/zh/{guides → plugin}/rsbuild-plugins/plugin-esbuild.mdx +0 -0
|
@@ -2,151 +2,85 @@
|
|
|
2
2
|
sidebar_position: 3
|
|
3
3
|
title: 运行时框架
|
|
4
4
|
---
|
|
5
|
+
|
|
5
6
|
# 运行时框架
|
|
6
7
|
|
|
7
8
|
Modern.js 的 BFF 支持不同的运行时框架,当前 Modern.js 的 BFF 支持两种运行时框架 [Express.js](https://expressjs.com/) 和 [Koa.js](https://koajs.com/)。
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
使用不同运行时框架时,有部分 API 会存在差异。
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
## 获取请求上下文
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
import { hook } from '@modern-js/runtime/server';
|
|
15
|
-
import { Request, Response, NextFunction } from 'express';
|
|
14
|
+
在 BFF 函数中,有时需要获取请求上下文,来处理更多逻辑。此时,根据不同的运行时框架,你需要从通过不同的 API 来获取:
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
addMiddleware(async (req: Request, res: Response, next: NextFunction) => {
|
|
19
|
-
if (req.url !== '/api/login') {
|
|
20
|
-
const sid = req?.cookies?.sid;
|
|
21
|
-
if (!sid) {
|
|
22
|
-
res.status(400);
|
|
23
|
-
res.json({ code: -1, message: 'need login' });
|
|
24
|
-
} else {
|
|
25
|
-
next();
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
28
|
-
next();
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
```
|
|
16
|
+
import { Tabs, Tab as TabItem } from "@theme";
|
|
33
17
|
|
|
34
|
-
|
|
18
|
+
<Tabs>
|
|
19
|
+
<TabItem value="express" label="Express.js" default>
|
|
35
20
|
|
|
36
|
-
```ts
|
|
37
|
-
|
|
38
|
-
|
|
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'
|
|
39
27
|
};
|
|
40
28
|
```
|
|
41
29
|
|
|
42
|
-
|
|
30
|
+
</TabItem>
|
|
31
|
+
<TabItem value="koa" label="Koa.js">
|
|
43
32
|
|
|
44
|
-
```ts
|
|
45
|
-
import {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
async function fetchMyApi() {
|
|
53
|
-
const { message } = await hello();
|
|
54
|
-
setText(message);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
fetchMyApi();
|
|
58
|
-
}, []);
|
|
59
|
-
|
|
60
|
-
return <p>{text}</p>;
|
|
33
|
+
```ts title="api/lambda/hello.ts"
|
|
34
|
+
import { useContext } from '@modern-js/runtime/koa'
|
|
35
|
+
export const get = async () => {
|
|
36
|
+
const ctx = useContext();
|
|
37
|
+
console.info(`access url: ${req.url}`);
|
|
38
|
+
return 'Hello Modern.js'
|
|
61
39
|
};
|
|
62
40
|
```
|
|
63
41
|
|
|
64
|
-
|
|
42
|
+
</TabItem>
|
|
43
|
+
</Tabs>
|
|
65
44
|
|
|
66
|
-
|
|
45
|
+
:::info
|
|
46
|
+
详细内容可以参考 [useContext](/apis/app/runtime/bff/use-context)。
|
|
47
|
+
:::
|
|
67
48
|
|
|
68
|
-
|
|
49
|
+
## 使用中间件
|
|
69
50
|
|
|
70
|
-
|
|
71
|
-
import { useState, useEffect } from 'react';
|
|
72
|
-
import { get as hello } from '@api/hello';
|
|
73
|
-
import { post as login } from '@api/login';
|
|
51
|
+
在 BFF 函数中,有时需要使用中间件,来处理更多逻辑。此时,根据不同的运行时框架,你需要从通过不同的 API 来获取:
|
|
74
52
|
|
|
75
|
-
|
|
76
|
-
|
|
53
|
+
<Tabs>
|
|
54
|
+
<TabItem value="express" label="Express.js" default>
|
|
77
55
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const { code } = await login();
|
|
81
|
-
if (code === 0) {
|
|
82
|
-
const { message } = await hello();
|
|
83
|
-
setText(message);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
fetchAfterLogin();
|
|
87
|
-
}, []);
|
|
56
|
+
```ts title="api/_app.ts"
|
|
57
|
+
import { hook } from '@modern-js/runtime/express';
|
|
88
58
|
|
|
89
|
-
|
|
90
|
-
|
|
59
|
+
export default hook(({ addMiddleware }) => {
|
|
60
|
+
addMiddleware((req, res, next) => {
|
|
61
|
+
req.query.id = 'koa';
|
|
62
|
+
next();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
91
65
|
```
|
|
92
66
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-

|
|
96
|
-
|
|
97
|
-
以上代码模拟了在 `/api/_app.ts` 中添加中间件的方式,实现了简易的登录功能。同样,可以在这个钩子文件中实现其他功能来扩展 BFF Server。
|
|
98
|
-
|
|
99
|
-
## 框架写法
|
|
100
|
-
|
|
101
|
-
框架写法下,Modern.js 不会收集 `api/_app.ts` 中的中间件,运行流程由插件自行控制。
|
|
102
|
-
|
|
103
|
-
### Express
|
|
67
|
+
</TabItem>
|
|
68
|
+
<TabItem value="koa" label="Koa.js">
|
|
104
69
|
|
|
105
|
-
|
|
70
|
+
```ts title="api/_app.ts"
|
|
71
|
+
import { hook } from '@modern-js/runtime/koa';
|
|
106
72
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const app = express();
|
|
113
|
-
|
|
114
|
-
app.put('/user', function (req, res) {
|
|
115
|
-
res.send('Got a PUT request at /user');
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
app.use(async (req, res, next) => {
|
|
119
|
-
console.info(`access url: ${req.url}`);
|
|
120
|
-
next();
|
|
73
|
+
export default hook(({ addMiddleware }) => {
|
|
74
|
+
addMiddleware(async (ctx, next) => {
|
|
75
|
+
ctx.req.query.id = 'koa';
|
|
76
|
+
await next();
|
|
77
|
+
});
|
|
121
78
|
});
|
|
122
|
-
|
|
123
|
-
export default app;
|
|
124
79
|
```
|
|
125
80
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Koa 框架写法与 Express 类似,支持在 `app.[tj]s` 定义 API Server 的启动逻辑,执行应用的初始化工作,添加全局中间件,声明路由,扩展原有框架等。
|
|
129
|
-
|
|
130
|
-
BFF 函数定义的路由会在 `app.ts` 文件定义的路由之后注册,所以在这里你也可以拦截 BFF 函数定义的路由,进行预处理或是提前响应。
|
|
131
|
-
|
|
132
|
-
:::caution 注意
|
|
133
|
-
在框架写法下,当没有 `app.ts` 的时候,Modern.js 默认会添加 `koa-body`;当有 `app.ts` 时,如果开发者希望使用带有 Body 的 BFF 函数,需要确保 `koa-body` 中间件已经添加。
|
|
81
|
+
</TabItem>
|
|
82
|
+
</Tabs>
|
|
134
83
|
|
|
84
|
+
:::info
|
|
85
|
+
详细内容可以参考 [hook](/apis/app/runtime/bff/hook)。
|
|
135
86
|
:::
|
|
136
|
-
|
|
137
|
-
```ts title=api/app.ts
|
|
138
|
-
import koa from 'koa';
|
|
139
|
-
|
|
140
|
-
const app = new Koa();
|
|
141
|
-
|
|
142
|
-
app.put('/user', function (req, res) {
|
|
143
|
-
res.send('Got a PUT request at /user');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
app.use(async (ctx, next) => {
|
|
147
|
-
console.info(`access url: ${ctx.url}`);
|
|
148
|
-
await next();
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
export default app;
|
|
152
|
-
```
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 1
|
|
3
|
-
title: 基础用法
|
|
4
|
-
---
|
|
5
1
|
# 基础用法
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
在 Modern.js 应用中,开发者可以在 `api/lambda` 目录下定义接口文件,并导出接口函数。在前端代码中,可以用文件引用的方式,直接调用这些接口函数,发起接口请求。
|
|
4
|
+
|
|
5
|
+
这种调用方式我们称为**一体化调用**,开发者无需编写前后端胶水层代码,并天然地保证前后端类型安全。
|
|
8
6
|
|
|
9
7
|
## 启用 BFF
|
|
10
8
|
|
|
@@ -14,20 +12,15 @@ import EnableBFF from "@site-docs/components/enable-bff"
|
|
|
14
12
|
|
|
15
13
|
## BFF 函数
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
:::caution
|
|
20
|
-
如果是框架模式(有 `api/lambda` 目录),需要创建 `api/lambda/hello.ts`
|
|
21
|
-
|
|
22
|
-
:::
|
|
15
|
+
允许使用一体化调用的函数,我们称为 **BFF 函数**。这里写一个最简单的 BFF 函数,首先创建 `api/lambda/hello.ts` 文件:
|
|
23
16
|
|
|
24
|
-
```ts title="api/hello.ts"
|
|
17
|
+
```ts title="api/lambda/hello.ts"
|
|
25
18
|
export const get = async () => 'Hello Modern.js';
|
|
26
19
|
```
|
|
27
20
|
|
|
28
|
-
接着在 `src/
|
|
21
|
+
接着在 `src/routes/page.tsx` 中直接引入函数并调用:
|
|
29
22
|
|
|
30
|
-
```tsx title=src/
|
|
23
|
+
```tsx title="src/routes/page.tsx"
|
|
31
24
|
import { useState, useEffect } from 'react';
|
|
32
25
|
import { get as hello } from '@api/hello';
|
|
33
26
|
|
|
@@ -41,56 +34,49 @@ export default () => {
|
|
|
41
34
|
};
|
|
42
35
|
```
|
|
43
36
|
|
|
44
|
-
:::
|
|
45
|
-
Modern.js
|
|
37
|
+
:::tip
|
|
38
|
+
在调用 `new` 命令后,Modern.js 生成器会自动在 `tsconfig.json` 中配置 `@api` 别名,因此可以直接通过别名的方式引入函数。
|
|
46
39
|
|
|
47
40
|
:::
|
|
48
41
|
|
|
49
|
-
在 `src/
|
|
42
|
+
在 `src/routes/page.tsx` 中引入的函数,会自动转换成接口调用,不需要再通过请求 SDK 或 Web Fetch 调用接口。
|
|
50
43
|
|
|
51
|
-
执行 `pnpm run dev`
|
|
44
|
+
执行 `pnpm run dev` 后,打开 `http://localhost:8080/` 可以看到页面已经展示了 BFF 函数返回的内容,在 Network 中可以看到页面向 `http://localhost:8080/api/hello` 发送了请求:
|
|
52
45
|
|
|
53
46
|

|
|
54
47
|
|
|
55
48
|
## 函数路由
|
|
56
49
|
|
|
57
|
-
Modern.js 中,BFF
|
|
58
|
-
|
|
59
|
-
函数写法下 `api/` 下的所有文件中的每个 BFF 函数都会映射为一个接口。框架写法下 `api/lambda` 下的所有文件中的每个 BFF 函数都会映射为一个接口。
|
|
60
|
-
|
|
61
|
-
:::note
|
|
62
|
-
函数写法和框架写法会在下一节详细介绍。
|
|
63
|
-
|
|
64
|
-
:::
|
|
50
|
+
Modern.js 中,BFF 函数对应的路由系统是基于文件系统实现的,也是一种**约定式路由**。`api/lambda` 下的所有文件中的每个 BFF 函数都会映射为一个接口,下面介绍几种路由的约定。
|
|
65
51
|
|
|
52
|
+
:::info
|
|
66
53
|
所有 BFF 函数生成的路由都带有统一的前缀,默认值为 `/api`。可以通过 [bff.prefix](/configure/app/bff/prefix) 设置公共路由的前缀。
|
|
67
|
-
|
|
68
|
-
下面介绍几种路由的约定。
|
|
54
|
+
:::
|
|
69
55
|
|
|
70
56
|
### 默认路由
|
|
71
57
|
|
|
72
58
|
以 `index.[jt]s` 命名的文件会被映射到上一层目录。
|
|
73
59
|
|
|
74
|
-
- `api/index.ts` -> `{prefix}/`
|
|
75
|
-
- `api/user/index.ts` -> `{prefix}/user`
|
|
60
|
+
- `api/lambda/index.ts` -> `{prefix}/`
|
|
61
|
+
- `api/lambda/user/index.ts` -> `{prefix}/user`
|
|
76
62
|
|
|
77
63
|
### 多层路由
|
|
78
64
|
|
|
79
65
|
支持解析嵌套的文件,如果创建嵌套文件夹结构,文件仍会以相同方式自动解析路由。
|
|
80
66
|
|
|
81
|
-
- `api/hello.ts` -> `{prefix}/hello`
|
|
82
|
-
- `api/user/list.ts` -> `{prefix}/user/list`
|
|
67
|
+
- `api/lambda/hello.ts` -> `{prefix}/hello`
|
|
68
|
+
- `api/lambda/user/list.ts` -> `{prefix}/user/list`
|
|
83
69
|
|
|
84
70
|
### 动态路由
|
|
85
71
|
|
|
86
|
-
同样的,创建命名带有 `[xxx]` 的文件夹或者文件,支持动态的命名路由参数。动态路由的函数参数规则可以看 [dynamac-path](/guides/advanced-features/bff/function#dynamic-path)
|
|
72
|
+
同样的,创建命名带有 `[xxx]` 的文件夹或者文件,支持动态的命名路由参数。动态路由的函数参数规则可以看 [dynamac-path](/guides/advanced-features/bff/function#dynamic-path)。
|
|
87
73
|
|
|
88
|
-
- `api/user/[username]/info.ts` -> `{prefix}/user/:username/info`
|
|
89
|
-
- `api/user/username/[action].ts` -> `{prefix}/user/username/:action`
|
|
74
|
+
- `api/lambda/user/[username]/info.ts` -> `{prefix}/user/:username/info`
|
|
75
|
+
- `api/lambda/user/username/[action].ts` -> `{prefix}/user/username/:action`
|
|
90
76
|
|
|
91
77
|
### 白名单
|
|
92
78
|
|
|
93
|
-
默认 `api/` 目录下所有文件都会当作 BFF 函数文件去解析,但以下文件不会被解析:
|
|
79
|
+
默认 `api/lambda/` 目录下所有文件都会当作 BFF 函数文件去解析,但以下文件不会被解析:
|
|
94
80
|
|
|
95
81
|
- 命名以 `_` 开头的文件。例如:`_utils.ts`。
|
|
96
82
|
- 命名以 `_` 开头的文件夹下所有文件。例如:`_utils/index.ts`、`_utils/cp.ts`。
|
|
@@ -100,20 +86,18 @@ Modern.js 中,BFF 函数对应的路由系统是基于文件系统实现的,
|
|
|
100
86
|
|
|
101
87
|
## RESTful API
|
|
102
88
|
|
|
103
|
-
Modern.js 的 BFF 函数需要遵循 RESTful API
|
|
104
|
-
|
|
105
|
-
:::info
|
|
106
|
-
假设函数允许自由定义参数,产出的路由必然由**私有协议**进行调用(原因是无法区分请求参数与请求体),而无法实现任意的 RESTful API。
|
|
89
|
+
Modern.js 的 BFF 函数需要遵循 RESTful API 标准来定义,开发者需要按照一系列规则来定义 BFF 函数。
|
|
107
90
|
|
|
108
|
-
|
|
91
|
+
:::tip 设计原则
|
|
92
|
+
BFF 函数不仅会在项目中被调用,也应该允许其他项目通过请求 SDK 或 Web fetch 调用。因此 Modern.js 没有在一体化调用时定义**私有协议**,而是通过标准的 HTTP Method,以及 `params`、`query`、`body` 等通用的 HTTP 请求参数来定义函数。
|
|
109
93
|
|
|
110
94
|
:::
|
|
111
95
|
|
|
112
|
-
###
|
|
96
|
+
### 函数导出规则
|
|
113
97
|
|
|
114
|
-
|
|
98
|
+
#### HTTP Method 具名函数
|
|
115
99
|
|
|
116
|
-
|
|
100
|
+
Modern.js BFF 函数的导出名决定了函数对应接口的 HTTP Method,如 `get`,`post` 等。例如导出一个 GET 接口:
|
|
117
101
|
|
|
118
102
|
```ts
|
|
119
103
|
export const get = async () => {
|
|
@@ -124,7 +108,7 @@ export const get = async () => {
|
|
|
124
108
|
};
|
|
125
109
|
```
|
|
126
110
|
|
|
127
|
-
按照以下例子,则可导出一个 `POST`
|
|
111
|
+
按照以下例子,则可导出一个 `POST` 接口:
|
|
128
112
|
|
|
129
113
|
```ts
|
|
130
114
|
export const post = async () => {
|
|
@@ -139,24 +123,46 @@ export const post = async () => {
|
|
|
139
123
|
|
|
140
124
|
- 名字是大小不敏感的,如果是 `GET`,写成 `get`、`Get`、`GEt`、`GET`,都可以准确识别。而默认导出,即 `export default xxx` 则会被映射为 `Get`。
|
|
141
125
|
|
|
142
|
-
|
|
126
|
+
#### 使用 Async 函数
|
|
143
127
|
|
|
144
|
-
|
|
145
|
-
需要注意的是,定义的函数都应该是异步的,与函数调用时类型有关,后面会提到。
|
|
128
|
+
Modern.js 推荐将 BFF 函数定义为 Async 异步函数,即使函数中不存在异步流程,例如:
|
|
146
129
|
|
|
147
|
-
|
|
130
|
+
```ts
|
|
131
|
+
export const get = async () => {
|
|
132
|
+
return {
|
|
133
|
+
name: 'Modern.js',
|
|
134
|
+
desc: '现代 web 工程方案',
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
```
|
|
148
138
|
|
|
149
|
-
|
|
139
|
+
这是因为在前端调用时,BFF 函数会自动转换成 HTTP 接口调用,而 HTTP 接口调用时异步的,在前端通常会这样使用:
|
|
140
|
+
|
|
141
|
+
```tsx title="src/routes/page.tsx"
|
|
142
|
+
import { useState, useEffect } from 'react';
|
|
143
|
+
import { get as hello } from '@api/hello';
|
|
144
|
+
|
|
145
|
+
export default () => {
|
|
146
|
+
const [text, setText] = useState('');
|
|
147
|
+
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
hello().then(setText);
|
|
150
|
+
}, []);
|
|
151
|
+
return <div>{text}</div>;
|
|
152
|
+
};
|
|
153
|
+
```
|
|
150
154
|
|
|
151
|
-
|
|
155
|
+
因此,为了保持类型定义与实际调用体验统一,我们推荐在定义 BFF 函数时将它设置为异步函数。
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
### 函数参数规则
|
|
158
|
+
|
|
159
|
+
函数参数规则分为两块,分别是请求路径中的动态路由(Dynamic Path)和请求选项(RequestOption)。
|
|
154
160
|
|
|
155
161
|
#### Dynamic Path
|
|
156
162
|
|
|
157
|
-
|
|
163
|
+
动态路由会作为 BFF 函数第一部分的入参,每个入参对应一段动态路由。例如以下示例,`level` 和 `id` 会作为前两个参数传递到函数中:
|
|
158
164
|
|
|
159
|
-
```ts title="api/[level]/[id].ts"
|
|
165
|
+
```ts title="api/lambda/[level]/[id].ts"
|
|
160
166
|
export default async (level: number, id: number) => {
|
|
161
167
|
const userData = await queryUser(level, uid);
|
|
162
168
|
return userData;
|
|
@@ -165,7 +171,7 @@ export default async (level: number, id: number) => {
|
|
|
165
171
|
|
|
166
172
|
在调用时直接传入动态参数:
|
|
167
173
|
|
|
168
|
-
```
|
|
174
|
+
```tsx title="src/routes/page.tsx"
|
|
169
175
|
import { useState, useEffect } from 'react';
|
|
170
176
|
import { get as getUser } from '@api/[level]/[id]';
|
|
171
177
|
|
|
@@ -186,7 +192,7 @@ Dynamic Path 之后的参数是包含 querystring、request body 的对象 `Requ
|
|
|
186
192
|
|
|
187
193
|
在不存在动态路由的普通函数中,可以从第一个入参中获取传入的 `data` 和 `query`,例如:
|
|
188
194
|
|
|
189
|
-
```ts title="api/hello.ts"
|
|
195
|
+
```ts title="api/lambda/hello.ts"
|
|
190
196
|
import type { RequestOption } from '@modern-js/runtime/server';
|
|
191
197
|
|
|
192
198
|
export async function post({
|
|
@@ -216,7 +222,7 @@ export async function post({ query, data }: { query: IQuery; data: IData }) {
|
|
|
216
222
|
|
|
217
223
|
当函数文件使用动态路由规则时,动态路由会在 `RequestOption` 对象参数前。
|
|
218
224
|
|
|
219
|
-
```ts title="api/[sku]/[id]/item.ts"
|
|
225
|
+
```ts title="api/lambda/[sku]/[id]/item.ts"
|
|
220
226
|
export async function post(
|
|
221
227
|
sku: string,
|
|
222
228
|
id: string,
|
|
@@ -231,7 +237,7 @@ export async function post(
|
|
|
231
237
|
|
|
232
238
|
调用时也按照函数定义,传入对应的参数即可:
|
|
233
239
|
|
|
234
|
-
```ts title="
|
|
240
|
+
```ts title="src/routes/page.tsx"
|
|
235
241
|
import { post } from '@api/[sku]/[id]/item';
|
|
236
242
|
|
|
237
243
|
export default () => {
|
|
@@ -250,4 +256,8 @@ export default () => {
|
|
|
250
256
|
};
|
|
251
257
|
```
|
|
252
258
|
|
|
253
|
-
|
|
259
|
+
## 扩展 BFF 函数
|
|
260
|
+
|
|
261
|
+
import ExtendBFF from "@site-docs/components/extend-bff-function"
|
|
262
|
+
|
|
263
|
+
<ExtendBFF/>
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
sidebar_position: 4
|
|
3
|
-
title: 自定义请求 SDK
|
|
4
|
-
---
|
|
5
|
-
# 自定义请求 SDK
|
|
1
|
+
# 扩展一体化调用 SDK
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
BFF 函数的一体化调用在 CSR 和 SSR 是同构的。Modern.js 封装的请求 SDK,在浏览器端依赖了 [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch),在服务端依赖了 [node-fetch](https://www.npmjs.com/package/node-fetch)。但在实际业务场景下,有时需要对请求或响应做一些额外的处理,例如:
|
|
8
4
|
|
|
9
5
|
- 在请求头中写入鉴权信息
|
|
10
6
|
- 对响应的数据或错误进行统一的处理
|
|
11
7
|
- 特定平台无法使用浏览器的原生 fetch 函数,需要使用其他方式发送请求
|
|
12
8
|
|
|
13
|
-
针对上述的场景,Modern.js 提供了 `configure`
|
|
9
|
+
针对上述的场景,Modern.js 提供了 `configure` 函数,开放了一系列扩展能力,可以用它配置 ssr 透传请求头,添加拦截器,自定义请求 SDK。
|
|
14
10
|
|
|
15
11
|
:::caution 注意
|
|
16
12
|
`configure` 函数的调用需要在所有 BFF 请求发送前调用,以确保覆盖默认的请求配置。
|
|
@@ -18,42 +14,42 @@ Modern.js 的 BFF 在 CSR 和 SSR 是同构的。在浏览器端依赖了[Fetch
|
|
|
18
14
|
:::
|
|
19
15
|
|
|
20
16
|
|
|
21
|
-
```
|
|
17
|
+
```tsx title="routes/page.tsx"
|
|
22
18
|
import { configure } from '@modern-js/runtime/bff';
|
|
23
19
|
|
|
24
|
-
configure({
|
|
25
|
-
|
|
20
|
+
configure({
|
|
21
|
+
// ...
|
|
26
22
|
})
|
|
23
|
+
|
|
24
|
+
const Index = () => <div>Hello world</div>
|
|
25
|
+
export default Index;
|
|
27
26
|
```
|
|
28
27
|
|
|
29
|
-
## 配置
|
|
28
|
+
## 配置 SSR 透传请求头
|
|
30
29
|
|
|
31
|
-
在同时使用
|
|
30
|
+
在同时使用 Modern.js SSR 和 BFF 的场景下,常常需要将 SSR 页面请求上的一些请求头信息,透传给 BFF 服务。
|
|
32
31
|
|
|
33
32
|
例如项目有页面地址是 `https://website.com`,该页面是 SSR 的,在组件中会调用 API 接口 `https://website.com/api/info`,该接口需要用户的 cookie 信息做鉴权。页面在请求该 API 接口时,需要将 SSR 页面请求的 `cookie` 传给 BFF。
|
|
34
33
|
|
|
35
34
|
目前以下请求头在 Modernjs 中是自动透传的:
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
- x-tt-logid
|
|
39
|
-
|
|
40
|
-
- x-tt-stress
|
|
41
|
-
|
|
42
|
-
可以通过 `configure` 配置请求头。例如以下例子,Modern.js 会自动将 SSR 页面请求的 cookie 信息透传给 BFF 服务:
|
|
36
|
+
```ts
|
|
37
|
+
['cookie', 'user-agent', 'x-tt-logid', 'x-tt-stress']
|
|
38
|
+
```
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
import { configure } from '@modern-js/runtime/bff';
|
|
40
|
+
可以通过 `configure` 配置请求头。例如以下例子,Modern.js 会自动将 SSR 页面请求的 `x-uid` 信息透传给 BFF 服务:
|
|
46
41
|
|
|
42
|
+
```tsx
|
|
47
43
|
configure({
|
|
48
44
|
allowedHeaders: ['x-uid']
|
|
49
45
|
})
|
|
50
46
|
```
|
|
51
47
|
|
|
52
|
-
##
|
|
48
|
+
## 添加拦截器
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
在有些业务场景下需要对请求和响应进行统一的处理,这种场景下可以通过**配置拦截器**满足需求:
|
|
55
51
|
|
|
56
|
-
```tsx
|
|
52
|
+
```tsx
|
|
57
53
|
configure({
|
|
58
54
|
// 这里的 request 是一体化默认的请求工具,interceptor 函数需返回一个新的 request。
|
|
59
55
|
// 新 request 的出参必须是 parse body 之后的结果
|
|
@@ -66,16 +62,11 @@ configure({
|
|
|
66
62
|
});
|
|
67
63
|
```
|
|
68
64
|
|
|
69
|
-
##
|
|
70
|
-
|
|
71
|
-
如果仅仅通过配置拦截器无法满足需求,需要对请求的 SDK 做进一步的自定义,可以通过 `configure` 函数配置自定义请求 SDK:
|
|
72
|
-
|
|
73
|
-
:::caution 注意
|
|
74
|
-
在 SSR 和一体化调用的场景下,在 SSR 向 BFF 服务发送请求时,Modern.js 会通过**服务发现**找到 BFF 服务内网 IP,并通过 IP 发送请求,以提高性能。如果使用自定义请求 SDK 会**失去这种优化**。
|
|
65
|
+
## 自定义请求 SDK
|
|
75
66
|
|
|
76
|
-
|
|
67
|
+
如果仅仅通过配置拦截器无法满足需求,希望自定义请求函数,也可以通过 `configure` 进行配置:
|
|
77
68
|
|
|
78
|
-
```tsx
|
|
69
|
+
```tsx
|
|
79
70
|
import nodeFetch from 'node-fetch';
|
|
80
71
|
|
|
81
72
|
const customFetch = (input: RequestInfo | URL, init: RequestInit) => {
|
|
@@ -92,13 +83,13 @@ configure({
|
|
|
92
83
|
});
|
|
93
84
|
```
|
|
94
85
|
|
|
95
|
-
|
|
86
|
+
配置自定义请求函数有以下约定:
|
|
96
87
|
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
- 如果是 SSR
|
|
88
|
+
- 函数的入参与浏览器中的 Fetch 或 node-fetch 对齐,所有 BFF 函数的一体化调用会通过该函数发送请求。
|
|
89
|
+
- 函数出参必须是接口实际返回的数据,不能是 Promise,否则会导致 BFF 函数无法正常返回数据。
|
|
90
|
+
- 如果是 SSR 项目,函数必须要同时支持浏览器端和服务器端发送请求。
|
|
100
91
|
|
|
101
|
-
|
|
92
|
+
下面是使用 axios 定制自定义请求函数的示例:
|
|
102
93
|
|
|
103
94
|
```tsx title="App.tsx"
|
|
104
95
|
import { configure } from '@modern-js/runtime/bff';
|
|
@@ -9,13 +9,17 @@ Modern.js 默认对构建性能进行了充分优化,但是随着业务场景
|
|
|
9
9
|
本文档提供了一些可选的提速策略,**开发者可以根据实际场景选取其中的部分策略**,从而进一步提升构建速度。
|
|
10
10
|
|
|
11
11
|
:::tip 📢 注意
|
|
12
|
-
在[优化产物体积](/guides/advanced-features/optimize-bundle
|
|
12
|
+
在[优化产物体积](/guides/advanced-features/page-performance/optimize-bundle)一文中介绍的策略也可以用于提升构建性能,这里不再重复介绍。
|
|
13
13
|
:::
|
|
14
14
|
|
|
15
15
|
## 通用优化策略
|
|
16
16
|
|
|
17
17
|
以下是一些通用的优化策略,对开发环境和生产环境均有提速效果,其中部分策略对包体积也有优化。
|
|
18
18
|
|
|
19
|
+
### 使用 Rspack 构建(推荐)
|
|
20
|
+
|
|
21
|
+
如果你还未使用 Rspack 构建,可以切换到 Rspack 构建模式来提升 5~10 倍的构建速度,请参考 [使用 Rspack](/guides/advanced-features/rspack-start.html) 来进行切换。
|
|
22
|
+
|
|
19
23
|
### 升级 Node.js 版本
|
|
20
24
|
|
|
21
25
|
通常来说,将 Node.js 更新到最新的 [LTS 版本](https://github.com/nodejs/release#release-schedule),有助于提升构建性能。
|
|
@@ -40,25 +44,6 @@ nvm default 18
|
|
|
40
44
|
node -v
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
### 使用 Rspack 构建
|
|
44
|
-
|
|
45
|
-
如果你对构建性能有更极致的需求,可以一键切换到 Rspack 构建模式,请参考 [使用 Rspack](/guides/advanced-features/rspack-start.html) 来进行切换。
|
|
46
|
-
|
|
47
|
-
### 使用 SWC 或 esbuild 编译
|
|
48
|
-
|
|
49
|
-
[SWC](https://swc.rs/) (Speedy Web Compiler) 是基于 `Rust` 语言编写的高性能 JavaScript 和 TypeScript 转译和压缩工具。在 Polyfill 和语法降级方面可以和 Babel 提供一致的能力,并且性能比 Babel 高出一个数量级。
|
|
50
|
-
|
|
51
|
-
[esbuild](https://esbuild.github.io/) 是一款基于 Golang 开发的前端构建工具,具有打包、编译和压缩 JavaScript 代码的功能,相比传统的打包编译工具,esbuild 在性能上有显著提升。
|
|
52
|
-
|
|
53
|
-
Modern.js 提供了 SWC 插件和 esbuild 插件,让你能使用 SWC 或 esbuild 代替 babel-loader、ts-loader 和 terser 等库进行代码编译和压缩。详见:
|
|
54
|
-
|
|
55
|
-
- [SWC 插件文档](/configure/app/tools/swc.html)
|
|
56
|
-
- [esbuild 插件文档](/configure/app/tools/esbuild.html)
|
|
57
|
-
|
|
58
|
-
:::tip SWC vs esbuild
|
|
59
|
-
SWC 编译产物的兼容性较好,支持注入 core-js 等 Polyfill,并且功能更加完备,因此推荐优先使用 SWC 插件。
|
|
60
|
-
:::
|
|
61
|
-
|
|
62
47
|
### 避免使用 ts-loader
|
|
63
48
|
|
|
64
49
|
默认情况下,Modern.js 使用 Babel 编译 TS 文件,开启 [tools.tsLoader](/configure/app/tools/ts-loader.html) 选项后,会使用 `ts-loader` 编译 TS 文件。
|
|
@@ -118,7 +103,7 @@ export default {
|
|
|
118
103
|
|
|
119
104
|
### 调整 Browserslist 范围
|
|
120
105
|
|
|
121
|
-
这项优化的原理与[「提升 Browserslist 范围」](/guides/advanced-features/optimize-bundle
|
|
106
|
+
这项优化的原理与[「提升 Browserslist 范围」](/guides/advanced-features/page-performance/optimize-bundle#adjust-browserslist)类似,区别在于,我们可以为开发环境和生产环境设置不同的 browserslist,从而减少开发环境下的编译开销。
|
|
122
107
|
|
|
123
108
|
比如,你可以在 `package.json` 中添加以下配置,表示在开发环境下只兼容最新的浏览器,在生产环境下兼容实际需要的浏览器:
|
|
124
109
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
["code-split", "inline-assets", "optimize-bundle"]
|
|
@@ -39,7 +39,7 @@ export default defineConfig({
|
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
:::tip
|
|
42
|
-
如果你当前版本低于 MAJOR_VERSION.59.0
|
|
42
|
+
如果你当前版本低于 MAJOR_VERSION.59.0,可通过执行 `npx modern upgrade` 进行升级。
|
|
43
43
|
:::
|
|
44
44
|
|
|
45
45
|
import RspackPrecautions from '@modern-js/builder-doc/docs/zh/shared/rspackPrecautions.md';
|
|
@@ -104,7 +104,7 @@ export default defineConfig<'rspack'>({
|
|
|
104
104
|
|
|
105
105
|

|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
### 修改内置 Rspack 版本
|
|
108
108
|
|
|
109
109
|
可以使用 pnpm / yarn / npm 等包管理工具自带的依赖升级功能来将 Rspack 强制升级到指定版本。
|
|
110
110
|
|