@modern-js/main-doc 2.60.5 → 2.60.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/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
|
},
|