@modern-js/main-doc 0.0.0-nightly-20240909025816 → 0.0.0-nightly-20240910170704
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/api/lambda.mdx +4 -48
- package/docs/en/apis/app/hooks/api/middleware.mdx +11 -0
- package/docs/en/components/enable-bff.mdx +19 -2
- package/docs/en/components/extend-bff-function.mdx +5 -0
- package/docs/en/configure/app/auto-load-plugin.mdx +4 -0
- 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 +2 -2
- 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 +1 -1
- package/docs/en/guides/basic-features/static-assets.mdx +1 -1
- 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/components/enable-bff.mdx +19 -2
- package/docs/zh/components/extend-bff-function.mdx +5 -0
- package/docs/zh/configure/app/auto-load-plugin.mdx +4 -0
- 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 +2 -2
- package/docs/zh/guides/advanced-features/page-performance/_meta.json +1 -0
- package/docs/zh/guides/advanced-features/rsbuild-plugin.mdx +1 -1
- 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/static-assets.mdx +1 -1
- package/i18n.json +4 -0
- package/package.json +4 -4
- package/rspress.config.ts +1 -3
- 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/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/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/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
@@ -1,10 +1,8 @@
|
|
1
|
-
---
|
2
|
-
sidebar_position: 1
|
3
|
-
title: Basic Usage
|
4
|
-
---
|
5
1
|
# Basic Usage
|
6
2
|
|
7
|
-
|
3
|
+
In a Modern.js application, developers can define API files under the `api/lambda` directory and export API functions from these files. In the frontend code, these API functions can be directly invoked by importing the file, which initiates the API requests.
|
4
|
+
|
5
|
+
This invocation method is called **unified invocation**, where developers do not need to write glue code for the frontend and backend separately, thereby ensuring type safety across both.
|
8
6
|
|
9
7
|
## Enable BFF
|
10
8
|
|
@@ -12,17 +10,17 @@ import EnableBFF from "@site-docs-en/components/enable-bff"
|
|
12
10
|
|
13
11
|
<EnableBFF/>
|
14
12
|
|
15
|
-
## BFF
|
13
|
+
## BFF Functions
|
16
14
|
|
17
|
-
|
15
|
+
Functions that allow unified invocation are called **BFF Functions**. Here is an example of the simplest BFF function. First, create the `api/lambda/hello.ts` file:
|
18
16
|
|
19
|
-
```ts title="api/hello.ts"
|
17
|
+
```ts title="api/lambda/hello.ts"
|
20
18
|
export const get = async () => 'Hello Modern.js';
|
21
19
|
```
|
22
20
|
|
23
|
-
Then
|
21
|
+
Then, import and invoke the function directly in `src/routes/page.tsx`:
|
24
22
|
|
25
|
-
```tsx title=src/
|
23
|
+
```tsx title="src/routes/page.tsx"
|
26
24
|
import { useState, useEffect } from 'react';
|
27
25
|
import { get as hello } from '@api/hello';
|
28
26
|
|
@@ -36,131 +34,142 @@ export default () => {
|
|
36
34
|
};
|
37
35
|
```
|
38
36
|
|
39
|
-
:::
|
40
|
-
Modern.js generator
|
41
|
-
|
37
|
+
:::tip
|
38
|
+
After running the `new` command, the Modern.js generator will automatically configure the `@api` alias in `tsconfig.json`, allowing you to import functions directly using the alias.
|
42
39
|
:::
|
43
40
|
|
44
|
-
The
|
41
|
+
The function imported in `src/routes/page.tsx` will be automatically converted into an API call, eliminating the need to use an SDK or Web Fetch to call the API.
|
45
42
|
|
46
|
-
|
43
|
+
After running `pnpm run dev`, open `http://localhost:8080/` and you can see that the page displays the content returned by the BFF function. In the Network tab, you can see a request was made to `http://localhost:8080/api/hello`.
|
47
44
|
|
48
45
|

|
49
46
|
|
50
|
-
##
|
47
|
+
## Function Routes
|
51
48
|
|
52
|
-
In Modern.js, the
|
53
|
-
|
54
|
-
In **Function Mode**, All files under `api/` will map to an interface. In **Framework Mode**, All files under `api/lambda` will map to an interface
|
55
|
-
|
56
|
-
:::note
|
57
|
-
Function Mode & Framework Mode will introduce soon.
|
49
|
+
In Modern.js, the routing system for BFF functions is implemented based on the file system, which is another form of **conventional routing**. Each BFF function in the `api/lambda` directory is mapped to an API route. Here are some routing conventions.
|
58
50
|
|
51
|
+
:::info
|
52
|
+
All routes generated by BFF functions have a common prefix, which defaults to `/api`. This can be configured using [bff.prefix](/configure/app/bff/prefix).
|
59
53
|
:::
|
60
54
|
|
61
|
-
|
55
|
+
### Default Routes
|
62
56
|
|
63
|
-
|
57
|
+
Files named `index.[jt]s` will be mapped to the parent directory.
|
64
58
|
|
65
|
-
|
59
|
+
- `api/lambda/index.ts` -> `{prefix}/`
|
60
|
+
- `api/lambda/user/index.ts` -> `{prefix}/user`
|
66
61
|
|
67
|
-
|
62
|
+
### Nested Routes
|
68
63
|
|
69
|
-
|
70
|
-
- `api/user/index.ts` -> `{prefix}/user`
|
64
|
+
Nested directories are supported, and files will be automatically parsed into routes in the same way.
|
71
65
|
|
72
|
-
|
66
|
+
- `api/lambda/hello.ts` -> `{prefix}/hello`
|
67
|
+
- `api/lambda/user/list.ts` -> `{prefix}/user/list`
|
73
68
|
|
74
|
-
|
69
|
+
### Dynamic Routes
|
75
70
|
|
76
|
-
|
77
|
-
- `api/user/list.ts` -> `{prefix}/user/list`
|
71
|
+
Similarly, creating a directory or file with `[xxx]` in the name supports dynamic route parameters. The rules for dynamic route function parameters can be found in [dynamic-path](/guides/advanced-features/bff/function#dynamic-path).
|
78
72
|
|
79
|
-
|
73
|
+
- `api/lambda/user/[username]/info.ts` -> `{prefix}/user/:username/info`
|
74
|
+
- `api/lambda/user/username/[action].ts` -> `{prefix}/user/username/:action`
|
80
75
|
|
81
|
-
|
76
|
+
### Whitelist
|
82
77
|
|
83
|
-
|
84
|
-
- `api/user/username/[action].ts` -> `{prefix}/user/username/:action`
|
78
|
+
By default, all files under the `api/lambda/` directory are parsed as BFF function files, but the following files are ignored:
|
85
79
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
-
|
91
|
-
- files in directory which name start with `_`, for example `_utils/index.ts`、`_utils/cp.ts`.
|
92
|
-
- test files, for example `foo.test.ts`.
|
93
|
-
- type files, for example `hello.d.ts`.
|
94
|
-
- files in `node_module`.
|
80
|
+
- Files starting with an underscore `_`. For example: `_utils.ts`.
|
81
|
+
- Files under directories starting with an underscore `_`. For example: `_utils/index.ts`, `_utils/cp.ts`.
|
82
|
+
- Test files. For example: `foo.test.ts`.
|
83
|
+
- TypeScript type files. For example: `hello.d.ts`.
|
84
|
+
- Files under `node_modules`.
|
95
85
|
|
96
86
|
## RESTful API
|
97
87
|
|
98
|
-
Modern.js BFF functions need to
|
99
|
-
|
100
|
-
:::info
|
101
|
-
Assuming that the function allows free definition of parameters, the resulting route must be called by the **private protocol** (the reason is that the request parameters cannot be distinguished from the request body), and cannot implement any RESTful API.
|
102
|
-
|
103
|
-
If the service is only used for the application itself, there is no problem. but its **non-standard interface definition** cannot be integrated into the larger system. In the case of multiple systems working together (such as BFF low-code construction), other systems also need to follow the **private protocol**.
|
88
|
+
Modern.js BFF functions need to follow RESTful API standards for definition. Developers must define BFF functions according to a set of rules.
|
104
89
|
|
90
|
+
:::tip Design Principles
|
91
|
+
BFF functions should not only be invoked within the project but also be accessible to other projects via an SDK or Web fetch. Therefore, Modern.js does not define a **private protocol** for unified invocation but uses standard HTTP methods along with common HTTP request parameters like `params`, `query`, and `body` to define functions.
|
105
92
|
:::
|
106
93
|
|
107
|
-
### Function
|
94
|
+
### Function Export Rules
|
108
95
|
|
109
|
-
|
96
|
+
#### HTTP Method Named Functions
|
110
97
|
|
111
|
-
|
98
|
+
Modern.js BFF functions' export names determine the HTTP method for the corresponding API, such as `get`, `post`, etc. For example, to export a GET API:
|
112
99
|
|
113
100
|
```ts
|
114
101
|
export const get = async () => {
|
115
102
|
return {
|
116
103
|
name: 'Modern.js',
|
117
|
-
desc: '
|
104
|
+
desc: 'A modern web engineering solution',
|
118
105
|
};
|
119
106
|
};
|
120
107
|
```
|
121
108
|
|
122
|
-
|
109
|
+
The following example exports a `POST` API:
|
123
110
|
|
124
111
|
```ts
|
125
112
|
export const post = async () => {
|
126
113
|
return {
|
127
114
|
name: 'Modern.js',
|
128
|
-
desc: '
|
115
|
+
desc: 'A modern web engineering solution',
|
129
116
|
};
|
130
117
|
};
|
131
118
|
```
|
132
119
|
|
133
|
-
- Modern.js supports 9
|
120
|
+
- Modern.js supports 9 HTTP methods: `GET`, `POST`, `PUT`, `DELETE`, `CONNECT`, `TRACE`, `PATCH`, `OPTIONS`, and `HEAD`, which can be used as function export names.
|
134
121
|
|
135
|
-
-
|
122
|
+
- Names are case-insensitive. If the method is `GET`, it can be written as `get`, `Get`, `GEt`, or `GET`, and the default export, i.e., `export default xxx`, will be mapped to `Get`.
|
136
123
|
|
137
|
-
|
124
|
+
#### Using Async Functions
|
138
125
|
|
139
|
-
|
140
|
-
It should be noted that the defined functions should all be asynchronous, which is related to the type when the function is called, which will be mentioned later.
|
126
|
+
Modern.js recommends defining BFF functions as async functions, even if there is no asynchronous process in the function, for example:
|
141
127
|
|
142
|
-
|
128
|
+
```ts
|
129
|
+
export const get = async () => {
|
130
|
+
return {
|
131
|
+
name: 'Modern.js',
|
132
|
+
desc: 'A modern web engineering solution',
|
133
|
+
};
|
134
|
+
};
|
135
|
+
```
|
143
136
|
|
144
|
-
|
137
|
+
This is because, during frontend invocation, the BFF function will be automatically converted into an HTTP API call, and HTTP API calls are asynchronous. On the frontend, it is typically used like this:
|
145
138
|
|
146
|
-
|
139
|
+
```tsx title="src/routes/page.tsx"
|
140
|
+
import { useState, useEffect } from 'react';
|
141
|
+
import { get as hello } from '@api/hello';
|
147
142
|
|
148
|
-
|
143
|
+
export default () => {
|
144
|
+
const [text, setText] = useState('');
|
145
|
+
|
146
|
+
useEffect(() => {
|
147
|
+
hello().then(setText);
|
148
|
+
}, []);
|
149
|
+
return <div>{text}</div>;
|
150
|
+
};
|
151
|
+
```
|
152
|
+
|
153
|
+
Therefore, to keep the type definitions consistent with the actual invocation experience, we recommend defining BFF functions as async functions.
|
154
|
+
|
155
|
+
### Function Parameter Rules
|
156
|
+
|
157
|
+
Function parameter rules are divided into two parts: dynamic routes in the request path (`Dynamic Path`) and request options (`RequestOption`).
|
149
158
|
|
150
159
|
#### Dynamic Path
|
151
160
|
|
152
|
-
Dynamic
|
161
|
+
Dynamic routes will be the first part of the BFF function parameters, with each parameter corresponding to a segment of the dynamic route. For example, the `level` and `id` parameters will be passed to the function in the following example:
|
153
162
|
|
154
|
-
```ts title="api/[level]/[id].ts"
|
163
|
+
```ts title="api/lambda/[level]/[id].ts"
|
155
164
|
export default async (level: number, id: number) => {
|
156
165
|
const userData = await queryUser(level, uid);
|
157
166
|
return userData;
|
158
167
|
};
|
159
168
|
```
|
160
169
|
|
161
|
-
|
170
|
+
Invoke the function by directly passing in the dynamic parameters:
|
162
171
|
|
163
|
-
```
|
172
|
+
```tsx title="src/routes/page.tsx"
|
164
173
|
import { useState, useEffect } from 'react';
|
165
174
|
import { get as getUser } from '@api/[level]/[id]';
|
166
175
|
|
@@ -177,24 +186,41 @@ export default () => {
|
|
177
186
|
|
178
187
|
#### RequestOption
|
179
188
|
|
180
|
-
|
189
|
+
Parameters following the dynamic path are an object called `RequestOption`, which includes the query string and request body. This field is used to define the types for `data` and `query`.
|
181
190
|
|
182
|
-
In
|
191
|
+
In a standard function without dynamic routes, `RequestOption` can be obtained from the first parameter, for example:
|
183
192
|
|
184
|
-
```ts title="api/hello.ts"
|
193
|
+
```ts title="api/lambda/hello.ts"
|
185
194
|
import type { RequestOption } from '@modern-js/runtime/server';
|
186
195
|
|
187
196
|
export async function post({
|
188
197
|
query,
|
189
198
|
data,
|
190
199
|
}: RequestOption<Record<string, string>, Record<string, string>>) {
|
191
|
-
// do
|
200
|
+
// do something
|
192
201
|
}
|
193
202
|
```
|
194
203
|
|
195
|
-
|
204
|
+
Custom types can also be used here:
|
205
|
+
|
206
|
+
```ts title="api/lambda/hello.ts"
|
207
|
+
import type { RequestOption } from '@modern-js/runtime/server';
|
208
|
+
|
209
|
+
type IQuery = {
|
210
|
+
// some types
|
211
|
+
};
|
212
|
+
type IData = {
|
213
|
+
// some types
|
214
|
+
};
|
196
215
|
|
197
|
-
|
216
|
+
export async function post({ query, data }: { query: IQuery; data: IData }) {
|
217
|
+
// do something
|
218
|
+
}
|
219
|
+
```
|
220
|
+
|
221
|
+
When the function file uses dynamic routing, dynamic routes will precede the `RequestOption` object parameter.
|
222
|
+
|
223
|
+
```ts title="api/lambda/[sku]/[id]/item.ts"
|
198
224
|
export async function post(
|
199
225
|
sku: string,
|
200
226
|
id: string,
|
@@ -207,9 +233,9 @@ export async function post(
|
|
207
233
|
}
|
208
234
|
```
|
209
235
|
|
210
|
-
|
236
|
+
Pass the corresponding parameters when invoking the function according to its definition:
|
211
237
|
|
212
|
-
```ts title="
|
238
|
+
```ts title="src/routes/page.tsx"
|
213
239
|
import { post } from '@api/[sku]/[id]/item';
|
214
240
|
|
215
241
|
export default () => {
|
@@ -228,6 +254,8 @@ export default () => {
|
|
228
254
|
};
|
229
255
|
```
|
230
256
|
|
231
|
-
|
257
|
+
## Extend BFF Function
|
258
|
+
|
259
|
+
import ExtendBFF from "@site-docs-en/components/extend-bff-function"
|
232
260
|
|
233
|
-
|
261
|
+
<ExtendBFF/>
|
@@ -1,81 +1,70 @@
|
|
1
|
-
|
2
|
-
sidebar_position: 4
|
3
|
-
title: Custom request SDK
|
4
|
-
---
|
5
|
-
# Custom request SDK
|
1
|
+
# Extend Request SDK
|
6
2
|
|
7
|
-
|
3
|
+
The unified invocation of BFF functions is isomorphic in both CSR and SSR. The request SDK encapsulated by Modern.js relies on the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) on the browser side, and on [node-fetch](https://www.npmjs.com/package/node-fetch) on the server side. However, in actual business scenarios, additional processing may be required for requests or responses, such as:
|
8
4
|
|
9
|
-
-
|
10
|
-
- Uniform
|
11
|
-
-
|
5
|
+
- Writing authentication information in the request headers
|
6
|
+
- Uniform handling of response data or errors
|
7
|
+
- Using other methods to send requests when the native fetch function is unavailable on specific platforms
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
:::caution
|
16
|
-
The `configure` function call needs to be called before all BFF requests are sent, to ensure that the default request configuration is overridden.
|
9
|
+
To address these scenarios, Modern.js provides the `configure` function, which offers a series of extension capabilities. You can use it to configure SSR passthrough request headers, add interceptors, or customize the request SDK.
|
17
10
|
|
11
|
+
:::caution Note
|
12
|
+
The `configure` function needs to be called before all BFF requests are sent to ensure that the default request configuration is overridden.
|
18
13
|
:::
|
19
14
|
|
20
|
-
|
21
|
-
```ts title="App.tsx"
|
15
|
+
```tsx title="routes/page.tsx"
|
22
16
|
import { configure } from '@modern-js/runtime/bff';
|
23
17
|
|
24
18
|
configure({
|
25
|
-
|
19
|
+
// ...
|
26
20
|
})
|
27
|
-
```
|
28
21
|
|
29
|
-
|
22
|
+
const Index = () => <div>Hello world</div>
|
23
|
+
export default Index;
|
24
|
+
```
|
30
25
|
|
31
|
-
|
26
|
+
## Configuring SSR Passthrough Request Headers
|
32
27
|
|
33
|
-
|
28
|
+
When using both Modern.js SSR and BFF, it is often necessary to pass some request header information from the SSR page request to the BFF service.
|
34
29
|
|
35
|
-
|
30
|
+
For example, imagine a project with a page URL `https://website.com`. This page is rendered using SSR, and in the component, it will call the API endpoint `https://website.com/api/info`, which requires the user's cookie information for authentication. The page needs to pass the `cookie` of the SSR page request to the BFF when requesting this API endpoint.
|
36
31
|
|
37
|
-
|
38
|
-
- x-tt-logid
|
39
|
-
- user-agent
|
40
|
-
- x-tt-stress
|
32
|
+
Currently, the following request headers are automatically passed through in Modern.js:
|
41
33
|
|
42
|
-
|
34
|
+
```ts
|
35
|
+
['cookie', 'user-agent', 'x-tt-logid', 'x-tt-stress']
|
36
|
+
```
|
43
37
|
|
44
|
-
|
45
|
-
import { configure } from '@modern-js/runtime/bff';
|
38
|
+
You can configure additional request headers using `configure`. For example, in the following snippet, Modern.js will automatically pass the `x-uid` information from the SSR page request to the BFF service:
|
46
39
|
|
40
|
+
```tsx
|
47
41
|
configure({
|
48
42
|
allowedHeaders: ['x-uid']
|
49
43
|
})
|
50
44
|
```
|
51
45
|
|
52
|
-
##
|
46
|
+
## Adding Interceptors
|
53
47
|
|
54
|
-
In
|
48
|
+
In some business scenarios, you may need to handle requests and responses uniformly. This can be achieved by **configuring interceptors**:
|
55
49
|
|
56
|
-
```tsx
|
50
|
+
```tsx
|
57
51
|
configure({
|
58
|
-
// The request here is the default request
|
59
|
-
// The
|
60
|
-
interceptor(request){
|
61
|
-
return async(url, params) => {
|
52
|
+
// The `request` here is the default request tool for unified invocation. The `interceptor` function needs to return a new request.
|
53
|
+
// The output of the new request must be the parsed body result.
|
54
|
+
interceptor(request) {
|
55
|
+
return async (url, params) => {
|
62
56
|
const res = await request(url, params);
|
63
57
|
return res.json();
|
64
58
|
};
|
65
|
-
}
|
59
|
+
}
|
66
60
|
});
|
67
61
|
```
|
68
62
|
|
69
|
-
##
|
70
|
-
|
71
|
-
If the requirements cannot be met by configuring interceptors alone and need to further customize the request SDK, you can configure the custom request SDK by using the `configure` function:
|
72
|
-
|
73
|
-
:::caution
|
74
|
-
Send a request to the BFF service when the server side renders, Modern.js will find the BFF service intranet IP via **service discovery** and send requests via IP to improve performance. This optimization is **lost** if a custom request SDK is used.
|
63
|
+
## Customizing the Request SDK
|
75
64
|
|
76
|
-
|
65
|
+
If configuring interceptors alone cannot meet your needs and you want to customize the request function, you can also configure it using `configure`:
|
77
66
|
|
78
|
-
```tsx
|
67
|
+
```tsx
|
79
68
|
import nodeFetch from 'node-fetch';
|
80
69
|
|
81
70
|
const customFetch = (input: RequestInfo | URL, init: RequestInit) => {
|
@@ -92,13 +81,13 @@ configure({
|
|
92
81
|
});
|
93
82
|
```
|
94
83
|
|
95
|
-
|
84
|
+
There are some conventions when configuring custom request functions:
|
96
85
|
|
97
|
-
- The
|
98
|
-
- The
|
99
|
-
-
|
86
|
+
- The function's parameters should align with the Fetch API or node-fetch in the browser. All unified invocations of BFF functions will send requests via this function.
|
87
|
+
- The function's output must be the actual data returned by the API, not a Promise, otherwise, the BFF function will not return data correctly.
|
88
|
+
- If it's an SSR project, the function must support sending requests on both the browser and server sides.
|
100
89
|
|
101
|
-
|
90
|
+
Below is an example of using axios to customize a request function:
|
102
91
|
|
103
92
|
```tsx title="App.tsx"
|
104
93
|
import { configure } from '@modern-js/runtime/bff';
|
@@ -108,7 +97,7 @@ configure({
|
|
108
97
|
async request(...config: Parameters<typeof fetch>) {
|
109
98
|
const [url, params] = config;
|
110
99
|
const res = await axios({
|
111
|
-
url: url as string, // Here
|
100
|
+
url: url as string, // Here we need to use `as` because fetch and axios types are somewhat incompatible
|
112
101
|
method: params?.method as Method,
|
113
102
|
data: params?.body,
|
114
103
|
headers: params?.headers as Headers,
|
@@ -116,4 +105,4 @@ configure({
|
|
116
105
|
return res.data;
|
117
106
|
},
|
118
107
|
});
|
119
|
-
```
|
108
|
+
```
|
@@ -9,7 +9,7 @@ Modern.js optimizes build performance by default, but as the project becomes lar
|
|
9
9
|
This document provides some optional speed-up strategies, developers can choose some of them to improve the build performance.
|
10
10
|
|
11
11
|
:::tip 📢 Notice
|
12
|
-
The strategies in [Bundle Size Optimization](/guides/advanced-features/optimize-bundle
|
12
|
+
The strategies in [Bundle Size Optimization](/guides/advanced-features/page-performance/optimize-bundle) can also be used to improve build performance, so we won't repeat them here.
|
13
13
|
:::
|
14
14
|
|
15
15
|
## General optimization strategy
|
@@ -118,7 +118,7 @@ export default {
|
|
118
118
|
|
119
119
|
### Adjust Browserslist for development
|
120
120
|
|
121
|
-
This strategy is similar to ["Adjust Browserslist"](/guides/advanced-features/optimize-bundle
|
121
|
+
This strategy is similar to ["Adjust Browserslist"](/guides/advanced-features/page-performance/optimize-bundle#adjust-browserslist), the difference is that we can set different browserslist for development and production environment, thereby reducing the compilation overhead in the development environment.
|
122
122
|
|
123
123
|
For example, you can add the following config to `package.json`, which means that only the latest browsers are compatible in the development environment, and the actual browsers are compatible in the production environment:
|
124
124
|
|
@@ -0,0 +1 @@
|
|
1
|
+
["code-split", "inline-assets", "optimize-bundle"]
|
@@ -220,7 +220,7 @@ However, when a crawler visits the page, it might need to load all content and o
|
|
220
220
|
|
221
221
|
Modern.js uses [isbot](https://www.npmjs.com/package/isbot) to determine if a request is from a crawler based on the `user-agent` header.
|
222
222
|
|
223
|
-
import StreamSSRPerformance from '@site-docs/components/stream-ssr-performance';
|
223
|
+
import StreamSSRPerformance from '@site-docs-en/components/stream-ssr-performance';
|
224
224
|
|
225
225
|
<StreamSSRPerformance />
|
226
226
|
|
@@ -587,4 +587,4 @@ Additionally, when using conventional routing, make sure to use the API from `@m
|
|
587
587
|
If you must directly use the React Router package's API (e.g., route behavior wrapped in a unified npm package), you can set [`source.alias`](/configure/app/source/alias) to point `react-router` and `react-router-dom` to the project's dependencies, avoiding the issue of two versions of React Router.
|
588
588
|
:::
|
589
589
|
|
590
|
-
import Motivation from '@site-docs/components/convention-routing-motivation';
|
590
|
+
import Motivation from '@site-docs-en/components/convention-routing-motivation';
|
@@ -76,7 +76,7 @@ console.log(largeImage); // "/static/largeImage.6c12aba3.png"
|
|
76
76
|
console.log(smallImage); // "data:image/png;base64,iVBORw0KGgo..."
|
77
77
|
```
|
78
78
|
|
79
|
-
For a more detailed introduction to asset inlining, please refer to the [Static Asset Inlining](/guides/advanced-features/inline-assets) chapter.
|
79
|
+
For a more detailed introduction to asset inlining, please refer to the [Static Asset Inlining](/guides/advanced-features/page-performance/inline-assets) chapter.
|
80
80
|
|
81
81
|
## Output Files
|
82
82
|
|
@@ -2,56 +2,13 @@
|
|
2
2
|
title: lambda/*.[tj]s
|
3
3
|
sidebar_position: 3
|
4
4
|
---
|
5
|
-
# lambda/*.[tj]s
|
6
|
-
|
7
|
-
在 [BFF 框架写法](/guides/advanced-features/bff/type.html#框架写法)下,声明 API 路由的文件。除了[某些约定文件](/apis/app/hooks/api/lambda#白名单)外,`lambda/` 目录下的文件会被注册为接口的路由。
|
8
|
-
|
9
|
-
:::info
|
10
|
-
使用 `api` 目录需要开启 BFF 功能,需要在项目下执行 new 命令启用「BFF」功能。
|
11
5
|
|
12
|
-
|
6
|
+
# lambda/*.[tj]s
|
13
7
|
|
14
|
-
|
15
|
-
该文件支持使用 `js` 或 `ts` 语言,但必须使用 `esm` 语法导出函数。
|
8
|
+
开启 BFF 后,`lambda/` 目录下的文件会按照约定被注册为 BFF 的路由。
|
16
9
|
|
10
|
+
:::note
|
11
|
+
文件支持使用 `js` 或 `ts` 语言,但必须使用 `esm` 语法导出函数。
|
17
12
|
:::
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
### 默认路由
|
22
|
-
|
23
|
-
路由系统会将以 `index` 命名的文件会被映射到上一层目录。
|
24
|
-
|
25
|
-
- `api/lambda/index.ts` -> `$BASENAME/`
|
26
|
-
- `api/lambda/user/index.ts` -> `$BASENAME/user`
|
27
|
-
|
28
|
-
### 多级路由
|
29
|
-
|
30
|
-
路由系统也支持解析多级的文件,如果创建文件夹结构,文件仍会以相同方式自动解析路由。
|
31
|
-
|
32
|
-
- `api/lambda/hello.ts` -> `$BASENAME/hello`
|
33
|
-
- `api/lambda/user/list.ts` -> `$BASENAME/user/list`
|
34
|
-
|
35
|
-
### 动态路由
|
36
|
-
|
37
|
-
路由系统支持通过 `[]` 命名的文件目录生成动态路由。
|
38
|
-
|
39
|
-
- `api/lambda/user/[username]/info.ts` -> `$BASENAME/user/:username/info`
|
40
|
-
- `api/lambda/user/[username]/delete.ts` -> `$BASENAME/user/:username/delete`
|
41
|
-
- `api/lambda/article/[id]/info.ts` -> `$BASENAME/article/:id/info`
|
42
|
-
|
43
|
-
其中的 `$BASENAME` 可以在 `modern.config.js` 中进行配置,默认值为 `/api`。
|
44
|
-
|
45
|
-
### 白名单
|
46
|
-
|
47
|
-
默认 `lambda` 目录下所有文件都会当作 BFF 函数文件去解析,但同样我们也设置了白名单,这些文件不被被解析:
|
48
|
-
|
49
|
-
- 命名以 `_` 开头的文件。例如:`_utils.ts`。
|
50
|
-
- 命名以 `_` 开头的文件夹下所有文件。例如:`_utils/index.ts`、`_utils/cp.ts`。
|
51
|
-
- 测试文件。例如:`foo.test.ts`。
|
52
|
-
- TypeScript 类型文件。例如:`hello.d.ts`。
|
53
|
-
- `node_module` 下的文件。
|
54
|
-
|
55
|
-
## 函数定义
|
56
|
-
|
57
|
-
和函数写法下[函数定义](/apis/app/hooks/api/api#函数定义)完全一致。
|
14
|
+
详细内容可以参考 [BFF 函数路由](/guides/advanced-features/bff/function.html#函数路由)。
|
@@ -1,5 +1,22 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
import { PackageManagerTabs } from '@theme';
|
2
|
+
|
3
|
+
1. 执行 `new` 命令:
|
4
|
+
|
5
|
+
<PackageManagerTabs command="run new" />
|
6
|
+
|
7
|
+
2. 按照提示,选择**启用 BFF 功能**:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
? 请选择你想要的操作 启用可选功能
|
11
|
+
? 请选择功能名称 启用「BFF」功能
|
12
|
+
? 请选择 BFF 类型 框架模式
|
13
|
+
```
|
14
|
+
|
15
|
+
:::note
|
16
|
+
目前推荐使用框架模式创建 BFF,后续我们将会移除 BFF 类型的概念。
|
17
|
+
:::
|
18
|
+
|
19
|
+
3. 根据选择的运行时框架,将下面的代码添加到 `modern.config.[tj]s` 中:
|
3
20
|
|
4
21
|
import { Tabs, Tab as TabItem } from "@theme";
|
5
22
|
|