@modern-js/main-doc 2.60.5 → 2.60.6
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/components/bff-upload.mdx +95 -0
- package/docs/en/configure/app/dev/https.mdx +3 -0
- package/docs/en/configure/app/tools/html-plugin.mdx +13 -0
- package/docs/en/configure/app/tools/terser.mdx +1 -1
- package/docs/en/configure/app/tools/ts-loader.mdx +6 -3
- package/docs/en/configure/app/tools/webpack-chain.mdx +3 -3
- package/docs/en/guides/advanced-features/bff/_meta.json +1 -1
- package/docs/en/guides/advanced-features/bff/upload.mdx +5 -0
- package/docs/zh/components/bff-upload.mdx +97 -0
- package/docs/zh/configure/app/dev/https.mdx +3 -0
- package/docs/zh/configure/app/tools/html-plugin.mdx +13 -0
- package/docs/zh/configure/app/tools/terser.mdx +1 -1
- package/docs/zh/configure/app/tools/ts-loader.mdx +6 -3
- package/docs/zh/configure/app/tools/webpack-chain.mdx +3 -3
- package/docs/zh/guides/advanced-features/bff/_meta.json +1 -1
- package/docs/zh/guides/advanced-features/bff/upload.mdx +5 -0
- package/package.json +4 -4
@@ -0,0 +1,95 @@
|
|
1
|
+
BFF combined with runtime framework provides file upload capabilities, supporting integrated calls and pure function manual calls.
|
2
|
+
|
3
|
+
### BFF Function
|
4
|
+
|
5
|
+
First, create the `api/lambda/upload.ts` file:
|
6
|
+
|
7
|
+
```ts title="api/lambda/upload.ts"
|
8
|
+
export const post = async ({ formData }: {formData: Record<string, any>}) => {
|
9
|
+
console.info('formData:', formData);
|
10
|
+
// do somethings
|
11
|
+
return {
|
12
|
+
data: {
|
13
|
+
code: 0,
|
14
|
+
},
|
15
|
+
};
|
16
|
+
};
|
17
|
+
```
|
18
|
+
:::tip
|
19
|
+
The `formData` parameter in the interface processing function can access files uploaded from the client side. It is an `Object` where the keys correspond to the field names used during the upload.
|
20
|
+
:::
|
21
|
+
|
22
|
+
|
23
|
+
### Integrated Calling
|
24
|
+
|
25
|
+
Next, directly import and call the function in `src/routes/upload/page.tsx`:
|
26
|
+
```tsx title="routes/upload/page.tsx"
|
27
|
+
import { upload } from '@api/upload';
|
28
|
+
import React from 'react';
|
29
|
+
|
30
|
+
export default (): JSX.Element => {
|
31
|
+
const [file, setFile] = React.useState<FileList | null>();
|
32
|
+
|
33
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
34
|
+
setFile(e.target.files);
|
35
|
+
};
|
36
|
+
|
37
|
+
const handleUpload = () => {
|
38
|
+
if (!file) {
|
39
|
+
return;
|
40
|
+
}
|
41
|
+
upload({
|
42
|
+
files: {
|
43
|
+
images: file,
|
44
|
+
},
|
45
|
+
});
|
46
|
+
};
|
47
|
+
|
48
|
+
return (
|
49
|
+
<div>
|
50
|
+
<input multiple type="file" onChange={handleChange} />
|
51
|
+
<button onClick={handleUpload}>upload</button>
|
52
|
+
</div>
|
53
|
+
);
|
54
|
+
};
|
55
|
+
```
|
56
|
+
:::tip
|
57
|
+
Note: The input type must be `{ formData: FormData }` for the upload to succeed.
|
58
|
+
:::
|
59
|
+
|
60
|
+
|
61
|
+
### Manual Calling
|
62
|
+
You can manually upload files using the `fetch API`, when calling `fetch`, set the `body` as `FormData` type and submit a post request.
|
63
|
+
|
64
|
+
```tsx title="routes/upload/page.tsx"
|
65
|
+
import React from 'react';
|
66
|
+
|
67
|
+
export default (): JSX.Element => {
|
68
|
+
const [file, setFile] = React.useState<FileList | null>();
|
69
|
+
|
70
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
71
|
+
setFile(e.target.files);
|
72
|
+
};
|
73
|
+
|
74
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
75
|
+
e.preventDefault();
|
76
|
+
const formData = new FormData();
|
77
|
+
if (file) {
|
78
|
+
for (let i = 0; i < file.length; i++) {
|
79
|
+
formData.append('images', file[i]);
|
80
|
+
}
|
81
|
+
await fetch('/api/upload', {
|
82
|
+
method: 'POST',
|
83
|
+
body: formData,
|
84
|
+
});
|
85
|
+
}
|
86
|
+
};
|
87
|
+
|
88
|
+
return (
|
89
|
+
<form onSubmit={handleSubmit}>
|
90
|
+
<input multiple type="file" onChange={handleChange} />
|
91
|
+
<button type="submit">upload</button>
|
92
|
+
</form>
|
93
|
+
);
|
94
|
+
};
|
95
|
+
```
|
@@ -18,6 +18,19 @@ const defaultOptions = {
|
|
18
18
|
filename, // 基于 `output.distPath` 和 `entryName` 生成
|
19
19
|
templateParameters, // 对应 `html.templateParameters` 配置
|
20
20
|
chunks: [entryName],
|
21
|
+
minify: { // // generated based on `output.disableMinimize` and `output.minify`
|
22
|
+
removeComments: false,
|
23
|
+
useShortDoctype: true,
|
24
|
+
keepClosingSlash: true,
|
25
|
+
collapseWhitespace: true,
|
26
|
+
removeRedundantAttributes: true,
|
27
|
+
removeScriptTypeAttributes: true,
|
28
|
+
removeStyleLinkTypeAttributes: true,
|
29
|
+
removeEmptyAttributes: true,
|
30
|
+
minifyJS, // generated based on `output.charset`, `output.legalComments` and `performance.removeConsole`
|
31
|
+
minifyCSS: true,
|
32
|
+
minifyURLs: true,
|
33
|
+
},
|
21
34
|
};
|
22
35
|
```
|
23
36
|
|
@@ -52,5 +52,5 @@ export default {
|
|
52
52
|
```
|
53
53
|
|
54
54
|
:::tip Disable code minification
|
55
|
-
If you need to disable code minification, you can use the [output.
|
55
|
+
If you need to disable code minification, you can use the [output.minify](/configure/app/output/minify) configuration.
|
56
56
|
:::
|
@@ -8,10 +8,13 @@ title: tsLoader
|
|
8
8
|
- **Default:** `undefined`
|
9
9
|
- **Bundler:** `only support webpack`
|
10
10
|
|
11
|
-
:::warning
|
12
|
-
|
11
|
+
:::warning Deprecated
|
12
|
+
|
13
|
+
ts-loader is not recommended for use in the project, because:
|
14
|
+
|
15
|
+
- ts-loader cannot be used with certain features such as [source.transformImport](/configure/app/source/transform-import) and [tools.styledComponents](/configure/app/tools/styled-components) provided by Babel & SWC.
|
16
|
+
- Rspack does not support ts-loader.
|
13
17
|
|
14
|
-
ts-loader cannot be used with certain features such as [source.transformImport](https://modernjs.dev/en/configure/app/source/transform-import.html) and [tools.styledComponents](https://modernjs.dev/en/configure/app/tools/styled-components.html) provided by Babel & SWC.
|
15
18
|
:::
|
16
19
|
|
17
20
|
`ts-loader` is not enabled by default in the project. When `tools.tsLoader` is not undefined, builder will use ts-loader instead of babel-loader to compile TypeScript code.
|
@@ -227,8 +227,8 @@ For example, the `RULE.STYLUS` rule exists only when the Stylus plugin is regist
|
|
227
227
|
| `PLUGIN.REACT_FAST_REFRESH` | correspond to `ReactFastRefreshPlugin` |
|
228
228
|
| `PLUGIN.NODE_POLYFILL_PROVIDE` | correspond to `ProvidePlugin` for node polyfills |
|
229
229
|
| `PLUGIN.SUBRESOURCE_INTEGRITY` | correspond to `webpack-subresource-integrity` |
|
230
|
-
| `PLUGIN.ASSETS_RETRY` | correspond to webpack static asset retry plugin
|
231
|
-
| `PLUGIN.AUTO_SET_ROOT_SIZE` | correspond to automatically set root font size plugin
|
230
|
+
| `PLUGIN.ASSETS_RETRY` | correspond to webpack static asset retry plugin |
|
231
|
+
| `PLUGIN.AUTO_SET_ROOT_SIZE` | correspond to automatically set root font size plugin |
|
232
232
|
|
233
233
|
#### CHAIN_ID.MINIMIZER
|
234
234
|
|
@@ -243,4 +243,4 @@ For example, the `RULE.STYLUS` rule exists only when the Stylus plugin is regist
|
|
243
243
|
|
244
244
|
### Examples
|
245
245
|
|
246
|
-
For usage examples, please refer to: [
|
246
|
+
For usage examples, please refer to: [Rsbuild - bundlerChain examples](https://rsbuild.dev/guide/basic/configure-rspack#examples).
|
@@ -1 +1 @@
|
|
1
|
-
["function", "frameworks", "extend-server", "sdk"]
|
1
|
+
["function", "frameworks", "extend-server", "sdk", "upload"]
|
@@ -0,0 +1,97 @@
|
|
1
|
+
BFF 搭配运行时框架提供了文件上传能力,支持一体化调用及纯函数手动调用。
|
2
|
+
|
3
|
+
### BFF 函数
|
4
|
+
|
5
|
+
首先创建 `api/lambda/upload.ts` 文件:
|
6
|
+
|
7
|
+
```ts title="api/lambda/upload.ts"
|
8
|
+
export const post = async ({ formData }: {formData: Record<string, any>}) => {
|
9
|
+
console.info('formData:', formData);
|
10
|
+
// do somethings
|
11
|
+
return {
|
12
|
+
data: {
|
13
|
+
code: 0,
|
14
|
+
},
|
15
|
+
};
|
16
|
+
};
|
17
|
+
```
|
18
|
+
:::tip
|
19
|
+
通过接口处理函数入参中的 `formData` 可以获取客户端上传的文件。值为 `Object`,key 为上传时的字段名。
|
20
|
+
:::
|
21
|
+
|
22
|
+
### 一体化调用
|
23
|
+
|
24
|
+
接着在 `src/routes/upload/page.tsx` 中直接引入函数并调用:
|
25
|
+
```tsx title="routes/upload/page.tsx"
|
26
|
+
import { post } from '@api/upload';
|
27
|
+
import React from 'react';
|
28
|
+
|
29
|
+
export default (): JSX.Element => {
|
30
|
+
const [file, setFile] = React.useState<FileList | null>();
|
31
|
+
|
32
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
33
|
+
setFile(e.target.files);
|
34
|
+
};
|
35
|
+
|
36
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
37
|
+
e.preventDefault();
|
38
|
+
const formData = new FormData();
|
39
|
+
if (file) {
|
40
|
+
for (let i = 0; i < file.length; i++) {
|
41
|
+
formData.append('images', file[i]);
|
42
|
+
}
|
43
|
+
post({
|
44
|
+
formData,
|
45
|
+
});
|
46
|
+
}
|
47
|
+
};
|
48
|
+
|
49
|
+
return (
|
50
|
+
<div>
|
51
|
+
<input multiple type="file" onChange={handleChange} />
|
52
|
+
<button onClick={handleUpload}>upload</button>
|
53
|
+
</div>
|
54
|
+
);
|
55
|
+
};
|
56
|
+
```
|
57
|
+
:::tip
|
58
|
+
注意:入参类型必须为:`{ formData: FormData }` 才会正确上传。
|
59
|
+
|
60
|
+
:::
|
61
|
+
|
62
|
+
### 手动上传
|
63
|
+
可以基于 `fetch API` 手动上传文件,需要在调用 `fetch` 时,将 `body` 设置为 `FormData` 类型并提交 `post` 请求。
|
64
|
+
|
65
|
+
```tsx title="routes/upload/page.tsx"
|
66
|
+
import React from 'react';
|
67
|
+
|
68
|
+
export default (): JSX.Element => {
|
69
|
+
const [file, setFile] = React.useState<FileList | null>();
|
70
|
+
|
71
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
72
|
+
setFile(e.target.files);
|
73
|
+
};
|
74
|
+
|
75
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
76
|
+
e.preventDefault();
|
77
|
+
const formData = new FormData();
|
78
|
+
if (file) {
|
79
|
+
for (let i = 0; i < file.length; i++) {
|
80
|
+
formData.append('images', file[i]);
|
81
|
+
}
|
82
|
+
await fetch('/api/upload', {
|
83
|
+
method: 'POST',
|
84
|
+
body: formData,
|
85
|
+
});
|
86
|
+
}
|
87
|
+
};
|
88
|
+
|
89
|
+
return (
|
90
|
+
<form onSubmit={handleSubmit}>
|
91
|
+
<input multiple type="file" onChange={handleChange} />
|
92
|
+
<button type="submit">upload</button>
|
93
|
+
</form>
|
94
|
+
);
|
95
|
+
};
|
96
|
+
|
97
|
+
```
|
@@ -18,6 +18,19 @@ const defaultOptions = {
|
|
18
18
|
filename, // 基于 `output.distPath` 和 `entryName` 生成
|
19
19
|
templateParameters, // 对应 `html.templateParameters` 配置
|
20
20
|
chunks: [entryName],
|
21
|
+
minify: { // 基于 `output.minify` 和 `output.disableMinimize` 生成
|
22
|
+
removeComments: false,
|
23
|
+
useShortDoctype: true,
|
24
|
+
keepClosingSlash: true,
|
25
|
+
collapseWhitespace: true,
|
26
|
+
removeRedundantAttributes: true,
|
27
|
+
removeScriptTypeAttributes: true,
|
28
|
+
removeStyleLinkTypeAttributes: true,
|
29
|
+
removeEmptyAttributes: true,
|
30
|
+
minifyJS, // 基于 `output.charset`、`output.legalComments` 和 `performance.removeConsole` 生成
|
31
|
+
minifyCSS: true,
|
32
|
+
minifyURLs: true,
|
33
|
+
},
|
21
34
|
};
|
22
35
|
```
|
23
36
|
|
@@ -8,10 +8,13 @@ title: tsLoader
|
|
8
8
|
- **默认值:** `undefined`
|
9
9
|
- **打包工具:** `仅支持 webpack`
|
10
10
|
|
11
|
-
:::warning
|
12
|
-
|
11
|
+
:::warning 废弃提示
|
12
|
+
|
13
|
+
不推荐在项目中使用 ts-loader,原因如下:
|
14
|
+
|
15
|
+
- 启用 ts-loader 时将无法使用 [source.transformImport](/configure/app/source/transform-import) 和 [tools.styledComponents](/configure/app/tools/styled-components) 等由 Babel 和 SWC 提供支持的能力。
|
16
|
+
- Rspack 不支持使用 ts-loader。
|
13
17
|
|
14
|
-
启用 ts-loader 时将无法使用 [source.transformImport](https://modernjs.dev/configure/app/source/transform-import.html) 和 [tools.styledComponents](https://modernjs.dev/configure/app/tools/styled-components.html) 等由 Babel 和 SWC 提供支持的能力。
|
15
18
|
:::
|
16
19
|
|
17
20
|
项目中默认不开启 ts-loader,当 `tools.tsLoader` 不为 undefined 则表示开启 ts-loader,同时禁用 babel-loader 对 TypeScript 的编译。
|
@@ -231,8 +231,8 @@ Modern.js 中预先定义了一些常用的 Chain ID,你可以通过这些 ID
|
|
231
231
|
| `PLUGIN.REACT_FAST_REFRESH` | 对应 `ReactFastRefreshPlugin` |
|
232
232
|
| `PLUGIN.NODE_POLYFILL_PROVIDE` | 对应处理 node polyfill 的 `ProvidePlugin` |
|
233
233
|
| `PLUGIN.SUBRESOURCE_INTEGRITY` | 对应 `webpack-subresource-integrity` |
|
234
|
-
| `PLUGIN.ASSETS_RETRY` | 对应 webpack 静态资源重试插件 `WebpackAssetsRetryPlugin`
|
235
|
-
| `PLUGIN.AUTO_SET_ROOT_SIZE` | 对应自动设置根字体大小插件 `AutoSetRootSizePlugin`
|
234
|
+
| `PLUGIN.ASSETS_RETRY` | 对应 webpack 静态资源重试插件 `WebpackAssetsRetryPlugin` |
|
235
|
+
| `PLUGIN.AUTO_SET_ROOT_SIZE` | 对应自动设置根字体大小插件 `AutoSetRootSizePlugin` |
|
236
236
|
|
237
237
|
#### CHAIN_ID.MINIMIZER
|
238
238
|
|
@@ -247,4 +247,4 @@ Modern.js 中预先定义了一些常用的 Chain ID,你可以通过这些 ID
|
|
247
247
|
|
248
248
|
### 使用示例
|
249
249
|
|
250
|
-
使用示例可参考:[
|
250
|
+
使用示例可参考:[Rsbuild - bundlerChain 使用示例](https://rsbuild.dev/zh/guide/basic/configure-rspack#%E7%A4%BA%E4%BE%8B)。
|
@@ -1 +1 @@
|
|
1
|
-
["function", "frameworks", "extend-server", "sdk"]
|
1
|
+
["function", "frameworks", "extend-server", "sdk", "upload"]
|
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.6",
|
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.6"
|
26
26
|
},
|
27
27
|
"devDependencies": {
|
28
|
-
"@rspress/shared": "1.
|
28
|
+
"@rspress/shared": "1.35.2",
|
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.3.1",
|
35
35
|
"react-dom": "^18.3.1",
|
36
|
-
"rspress": "1.
|
36
|
+
"rspress": "1.35.2",
|
37
37
|
"ts-node": "^10.9.1",
|
38
38
|
"typescript": "^5"
|
39
39
|
},
|