@modern-js/main-doc 2.58.1 → 2.58.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,201 @@
1
+ ---
2
+ sidebar_position: 3
3
+ ---
4
+
5
+ # Esbuild 插件
6
+
7
+ :::warning
8
+ **当前文档中的 esbuild 功能已停止迭代**,我们更推荐使用 Rspack + SWC 的方案,因为 Rspack + SWC 具备更好的构建性能、功能丰富度和产物兼容性。
9
+
10
+ 请参考[「使用 Rspack」](guides/advanced-features/rspack-start)了解更多。
11
+
12
+ :::
13
+
14
+ import Esbuild from '@modern-js/builder-doc/docs/zh/shared/esbuild.md';
15
+
16
+ <Esbuild />
17
+
18
+ ## 快速开始
19
+
20
+ ### 在 Modern.js 框架中使用
21
+
22
+ Modern.js 框架默认集成了 Builder 的 esbuild 插件,因此,你不需要手动安装和注册插件,只需要使用 [tools.esbuild](/configure/app/tools/esbuild.html) 配置项即可:
23
+
24
+ ```js
25
+ export default defineConfig({
26
+ tools: {
27
+ esbuild: {
28
+ loader: {
29
+ target: 'chrome61',
30
+ },
31
+ minimize: {
32
+ target: 'chrome61',
33
+ },
34
+ },
35
+ },
36
+ });
37
+ ```
38
+
39
+ ## 配置
40
+
41
+ 插件默认会开启代码转译和代码压缩的功能,你也可以通过配置来自定义插件的行为。
42
+
43
+ ### loader
44
+
45
+ - **类型:**
46
+
47
+ ```ts
48
+ type LoaderOptions = EsbuildLoaderOptions | false | undefined;
49
+ ```
50
+
51
+ - **默认值:**
52
+
53
+ ```ts
54
+ const defaultOptions = {
55
+ target: 'es2015',
56
+ charset: builderConfig.output.charset,
57
+ };
58
+ ```
59
+
60
+ 这个选项用于启用 JavaScript 和 TypeScript 的转译,启用时将会使用 esbuild-loader 替换 babel-loader 和 ts-loader。
61
+
62
+ 如果你需要修改转译参数,可以查看 [esbuild-loader 文档](https://github.com/privatenumber/esbuild-loader#loader)。
63
+
64
+ #### 设置 JSX 格式
65
+
66
+ 在使用 esbuild 进行代码转译时,esbuild 默认会读取 `tsconfig.json` 中的 `compilerOptions.jsx` 字段,来决定使用哪种 JSX 语法。
67
+
68
+ 因此,你需要在 `tsconfig.json` 中设置正确的 JSX 语法。
69
+
70
+ 比如 React 项目,需要将 `compilerOptions.jsx` 设置为 `react-jsx`:
71
+
72
+ ```json
73
+ {
74
+ "compilerOptions": {
75
+ "jsx": "react-jsx"
76
+ }
77
+ }
78
+ ```
79
+
80
+ #### 修改目标环境
81
+
82
+ 通过 `target` 选项来修改代码转译的目标环境。`target` 可以直接设置为 JavaScript 语言版本,比如 `es6`,`es2020`;也可以设置为若干个目标环境,每个目标环境都是一个环境名称后跟一个版本号,比如 `['chrome58', 'edge16' ,'firefox57']`。`target` 字段的详细介绍可以参考 [esbuild - target](https://esbuild.github.io/api/#target)。
83
+
84
+ target 支持设置为以下环境:
85
+
86
+ - chrome
87
+ - edge
88
+ - firefox
89
+ - ie
90
+ - ios
91
+ - node
92
+ - opera
93
+ - safari
94
+
95
+ ```ts
96
+ builderPluginEsbuild({
97
+ loader: {
98
+ target: 'chrome61',
99
+ },
100
+ });
101
+ ```
102
+
103
+ #### 关闭代码转译
104
+
105
+ 将 `loader` 设置为 `false` 来关闭 esbuild 代码转译,此时 Builder 会继续使用 Babel 来进行代码转译。
106
+
107
+ ```ts
108
+ builderPluginEsbuild({
109
+ loader: false,
110
+ });
111
+ ```
112
+
113
+ ### minimize
114
+
115
+ - **类型:**
116
+
117
+ ```ts
118
+ type MinimizeOptions = EsbuildMinifyOptions | false | undefined;
119
+ ```
120
+
121
+ - **默认值:**
122
+
123
+ ```ts
124
+ const defaultOptions = {
125
+ css: true,
126
+ target: 'es2015',
127
+ format: builderTarget === 'web' ? 'iife' : undefined,
128
+ };
129
+ ```
130
+
131
+ 这个选项用于启用 JavaScript 和 CSS 的代码压缩。
132
+
133
+ 如果你需要修改压缩参数,可以查看 [esbuild-loader 文档](https://github.com/privatenumber/esbuild-loader#minifyplugin)。
134
+
135
+ #### 修改目标环境
136
+
137
+ 通过 `target` 选项来修改代码压缩的目标环境。
138
+
139
+ ```ts
140
+ builderPluginEsbuild({
141
+ minimize: {
142
+ target: 'chrome61',
143
+ },
144
+ });
145
+ ```
146
+
147
+ #### 关闭代码压缩
148
+
149
+ 将 `minimize` 设置为 `false` 来关闭 esbuild 代码压缩,此时 Builder 会继续使用 Terser 进行代码压缩。
150
+
151
+ ```ts
152
+ builderPluginEsbuild({
153
+ minimize: false,
154
+ });
155
+ ```
156
+
157
+ ## esbuild 局限性
158
+
159
+ 虽然 esbuild 能给现有的 webpack 项目带来明显的构建性能提升,但这个工具在接入 Builder 时还存在一定的局限性,需要大家在接入的时候格外注意。
160
+
161
+ ### 兼容性
162
+
163
+ 使用 esbuild 进行代码转译时(即 `loader` 能力),esbuild 通常最低支持到 ES2015(即 ES6)语法,并且不具备自动注入 Polyfill 的能力。如果生产环境需要降级到 ES5 及以下的语法,建议使用 SWC 编译。
164
+
165
+ 你可以通过如下的配置指定目标语法版本:
166
+
167
+ ```ts
168
+ builderPluginEsbuild({
169
+ loader: {
170
+ target: 'es2015',
171
+ },
172
+ });
173
+ ```
174
+
175
+ 使用 esbuild 进行代码压缩时(即 `minimize` 能力),esbuild 可以在生产环境中进行压缩和混淆,通常最低支持到 ES2015 语法。
176
+
177
+ 如果设置压缩的 `target` 为 `es5`,需要保证所有代码已经被转义为 ES5 代码,否则会导致 esbuild 编译报错:`Transforming 'xxx' to the configured target environment ("es5") is not supported yet`。
178
+
179
+ 因此,对于生产环境需要兼容 ES5 及以下语法的项目,请谨慎开启 minimize 能力,建议使用 SWC 压缩。
180
+
181
+ 你可以通过如下的配置指定目标语法版本:
182
+
183
+ ```ts
184
+ builderPluginEsbuild({
185
+ minimize: {
186
+ target: 'es2015',
187
+ },
188
+ });
189
+ ```
190
+
191
+ ### 不支持 Babel 插件
192
+
193
+ 使用 esbuild 进行代码转译时,诸如 `babel-plugin-import` 等原有 Babel 插件的语法编译功能在开启 esbuild 后无法使用。并且由于 Builder 底层使用的是 esbuild 的 `Transform API`,因此不支持使用额外 esbuild 插件来进行自定义编译过程。
194
+
195
+ 如果你有 `babel-plugin-import` 等 Babel 插件相关诉求,可以使用 SWC 插件。
196
+
197
+ ### 产物体积
198
+
199
+ 使用 esbuild 压缩虽然带来了构建效率上的提升,但 esbuild 的压缩比例是低于 terser 的,因此**构建产物的体积会增大**,请根据业务情况酌情使用。通常来说,esbuild 比较适合中后台等对体积不敏感的场景。
200
+
201
+ 对于压缩工具之间的详细对比,可以参考 [minification-benchmarks](https://github.com/privatenumber/minification-benchmarks)。
@@ -0,0 +1,344 @@
1
+ ---
2
+ sidebar_position: 2
3
+ ---
4
+
5
+ # SWC 插件
6
+
7
+ import SWC from '@modern-js/builder-doc/docs/zh/shared/swc.md';
8
+
9
+ <SWC />
10
+
11
+ ## 适用场景
12
+
13
+ 在使用 SWC 插件之前,请先了解一下 SWC 插件的适用场景和局限性,以明确你的项目是否需要使用 SWC 插件。
14
+
15
+ ### Rspack 场景
16
+
17
+ 如果你的项目中已经使用了 Rspack 作为打包工具,那么你不需要接入 SWC 插件,因为 Rspack 默认会使用 SWC 进行转译和压缩,各个 SWC 编译能力可以开箱即用。
18
+
19
+ 如果你使用 Rspack 时配置了当前的 SWC 插件,它将不会产生任何效果。
20
+
21
+ ### Babel 插件
22
+
23
+ 如果你的项目需要注册一些自定义的 Babel 插件,由于 SWC 替代了 Babel 作为转译工具,因此使用 SWC 后,你将无法注册和使用 Babel 插件。
24
+
25
+ 对于大部分常见的 Babel 插件,你可以在 SWC 中找到对应的替代品,比如:
26
+
27
+ - `@babel/preset-env`: 使用 [presetEnv](#presetenv) 代替。
28
+ - `@babel/preset-react`: 使用 [presetReact](#presetreact) 代替。
29
+ - `babel-plugin-import`:使用 [source.transformImport](/configure/app/source/transform-import) 代替。
30
+ - `babel-plugin-lodash`:使用 [extensions.lodash](#extensionslodash) 代替。
31
+ - `@emotion/babel-plugin`:使用 [extensions.emotion](#extensionsemotion) 代替。
32
+ - `babel-plugin-styled-components`:使用 [extensions.styledComponents](#extensionsstyledcomponents) 代替。
33
+ - `@babel/plugin-react-transform-remove-prop-types`: 使用 [reactUtils.removePropTypes](#extensionsreactutils) 代替。
34
+
35
+ 如果你使用了 SWC 尚未支持的 Babel 插件能力,在切换到 SWC 编译后,将无法再使用它们。你可以到 [swc-plugins](https://github.com/web-infra-dev/swc-plugins) 仓库下通过 issues 进行反馈,我们会评估是否需要内置支持。
36
+
37
+ ### 产物体积
38
+
39
+ 在使用 SWC 来代替 [terser](https://github.com/terser/terser) 和 [cssnano](https://github.com/cssnano/cssnano) 进行代码压缩时,构建产物的体积可能会出现少量变化。在 JavaScript 代码压缩方面,SWC 的压缩率是优于 terser 的;在 CSS 代码压缩方面,SWC 的压缩率稍逊于 cssnano。
40
+
41
+ 对于压缩工具之间的详细对比,可以参考 [minification-benchmarks](https://github.com/privatenumber/minification-benchmarks)。
42
+
43
+ ## 快速开始
44
+
45
+ ### 在 Modern.js 框架中使用
46
+
47
+ Modern.js 框架对 Builder 的 SWC 插件进行了封装,你可以通过以下方式来使用:
48
+
49
+ import EnableSWC from '@modern-js/builder-doc/docs/zh/shared/enableSwc.md';
50
+
51
+ <EnableSWC />
52
+
53
+ That's it! 现在你可以在项目中无缝使用 SWC 的转译和压缩能力了。
54
+
55
+ ## 配置
56
+
57
+ - **类型:**
58
+
59
+ ```ts
60
+ type PluginConfig =
61
+ | ObjPluginConfig
62
+ | ((
63
+ config: ObjPluginConfig,
64
+ utils: { mergeConfig: typeof lodash.merge; setConfig: typeof lodash.set },
65
+ ) => ObjPluginConfig | void);
66
+
67
+ // SwcOptions 为 swc 配置项 https://swc.rs/docs/configuration/compilation
68
+ interface ObjPluginConfig extends SwcOptions {
69
+ presetReact?: ReactConfig;
70
+ presetEnv?: EnvConfig;
71
+ jsMinify?: boolean | JsMinifyOptions;
72
+ cssMinify?: boolean | CssMinifyOptions;
73
+ extensions?: Extensions;
74
+ overrides?: Overrides;
75
+ }
76
+ ```
77
+
78
+ 插件配置在 SWC 配置的基础上,为了简化部分深层配置和为提高开发体验,进行了部分拓展,例如当使用对象形式配置时,可以使用 `presetReact` 以及 `presetEnv` 快速配置 react 以及语法降级相关功能,另外不属于插件特有的配置也会直接透传给 swc。
79
+
80
+ 当使用函数形式配置时,则会传入插件内部产出的默认配置,可以对其进行修改或返回新的配置。
81
+
82
+ ### presetReact
83
+
84
+ - **类型:** SWC 中的 [react](https://swc.rs/docs/configuration/compilation#jsctransformreact) 配置。
85
+
86
+ 对标 `@babel/preset-react`。传入的值会与默认配置进行合并。
87
+
88
+ 插件默认会自动根据你的 `react` 版本确定 `runtime` 字段,如果 `react` 版本大于 17.0.0,会设置成 `automatic`,否则设置成 `classic`。
89
+
90
+ ### presetEnv
91
+
92
+ - **类型:** SWC 中的 [presetEnv](https://swc.rs/docs/configuration/supported-browsers#options)。
93
+
94
+ 对标 `@babel/preset-env`。传入的值会与默认配置进行合并。
95
+ 默认配置为:
96
+
97
+ ```ts
98
+ {
99
+ targets: '', // 自动从项目中获取 browserslist
100
+ mode: 'usage',
101
+ }
102
+ ```
103
+
104
+ ### jsMinify
105
+
106
+ - **类型:** `boolean` 或者 [terser 中的 compress 配置](https://terser.org/docs/api-reference.html#compress-options)。
107
+ - **默认值:** `{ compress: {}, mangle: true }`。
108
+
109
+ 如果配置 `false` 将不会使用 SWC 的压缩能力,配置 `true` 会启用默认压缩配置,如果配置是对象,则会与默认配置进行合并。
110
+
111
+ ### cssMinify
112
+
113
+ - **类型:** `boolean`
114
+ - **默认值:** `true`
115
+
116
+ 是否启用 SWC 对 CSS 文件进行压缩,若启用会使得 CSS 压缩性能提高,但压缩率会略微降低。
117
+
118
+ ### overrides
119
+
120
+ - **类型:**
121
+
122
+ ```ts
123
+ interface Overrides extends SwcOptions {
124
+ test: RegExp;
125
+ include: RegExp[];
126
+ exclude: RegExp[];
127
+ }
128
+ ```
129
+
130
+ - **默认值:** `undefined`
131
+
132
+ 对指定文件运用另外的配置。例如需要对 `foo.ts` 的语法降级成 ie 11,则可以如下配置:
133
+
134
+ ```ts
135
+ {
136
+ test: /foo.ts/,
137
+ env: { targets: 'ie 11' }
138
+ }
139
+ ```
140
+
141
+ 该配置会与默认配置进行合并,并且不会影响到其他文件。
142
+
143
+ ### extensions
144
+
145
+ - **类型:** `Object`
146
+
147
+ `extensions` 包含了从 Babel 移植过来的一些插件能力。
148
+
149
+ #### extensions.reactUtils
150
+
151
+ - **类型:**
152
+
153
+ ```ts
154
+ type ReactUtilsOptions = {
155
+ autoImportReact?: boolean;
156
+ removeEffect?: boolean;
157
+ removePropTypes?: {
158
+ mode?: 'remove' | 'unwrap' | 'unsafe-wrap';
159
+ removeImport?: boolean;
160
+ ignoreFilenames?: string[];
161
+ additionalLibraries?: string[];
162
+ classNameMatchers?: string[];
163
+ };
164
+ };
165
+ ```
166
+
167
+ 一些用于 `React` 的工具,包括以下配置项:
168
+
169
+ **reactUtils.autoImportReact**
170
+
171
+ - **类型:** `boolean`
172
+
173
+ 自动引入 `React`, `import React from 'react'`,用于 `jsx` 转换使用 `React.createElement`。
174
+
175
+ **reactUtils.removeEffect**
176
+
177
+ - **类型:** `boolean`
178
+
179
+ 移除 `useEffect` 调用。
180
+
181
+ **reactUtils.removePropTypes**
182
+
183
+ - **类型:**
184
+
185
+ ```ts
186
+ type RemovePropTypesOptions = {
187
+ mode?: 'remove' | 'unwrap' | 'unsafe-wrap';
188
+ removeImport?: boolean;
189
+ ignoreFilenames?: string[];
190
+ additionalLibraries?: string[];
191
+ classNameMatchers?: string[];
192
+ };
193
+ ```
194
+
195
+ 移除 `React` 组件在运行时的类型判断。移植自 [@babel/plugin-react-transform-remove-prop-types](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types)。
196
+
197
+ 相应配置和 `@babel/plugin-react-transform-remove-prop-types` 插件保持一致。
198
+
199
+ #### extensions.lodash
200
+
201
+ - **类型:**
202
+
203
+ ```ts
204
+ type LodashOptions = {
205
+ cwd?: string;
206
+ ids?: string[];
207
+ };
208
+ ```
209
+
210
+ - **默认值:**
211
+
212
+ ```ts
213
+ const defaultOptions = {
214
+ cwd: process.cwd(),
215
+ ids: ['lodash', 'lodash-es'],
216
+ };
217
+ ```
218
+
219
+ 移植自 [babel-plugin-lodash](https://github.com/lodash/babel-plugin-lodash),用于自动将 Lodash 的引用转换为按需引入,从而减少打包后的 Lodash 代码大小。
220
+
221
+ ```ts
222
+ // Input
223
+ import { get, throttle } from 'lodash';
224
+
225
+ // Output
226
+ import get from 'lodash/get';
227
+ import throttle from 'lodash/throttle';
228
+ ```
229
+
230
+ #### extensions.styledComponents
231
+
232
+ - **类型:**
233
+
234
+ ```ts
235
+ boolean | {
236
+ displayName?: boolean; // 默认开发模式开启, 生产模式关闭,
237
+ ssr?: boolean; // 默认开启
238
+ fileName?: boolean; // 默认开启
239
+ topLevelImportPaths?: string[]; // 默认空
240
+ meaninglessFileNames?: string[]; // 默认为 ["index"].
241
+ cssProp?: boolean; // 默认开启
242
+ namespace?: string; // 默认空
243
+ };
244
+ ```
245
+
246
+ 由 Next.js 团队移植自 [babel-plugin-styled-components](https://github.com/styled-components/babel-plugin-styled-components)。
247
+
248
+ #### extensions.emotion
249
+
250
+ - **类型:**
251
+
252
+ ```ts
253
+ boolean | {
254
+ sourceMap?: boolean, // 默认开启
255
+ autoLabel?: 'never' | 'dev-only' | 'always', // 默认 'dev-only'
256
+ // 默认 '[local]'.
257
+ // 允许的值为: `[local]` `[filename]` 以及 `[dirname]`
258
+ // 只有当 autoLabel 设置成 'dev-only' 或者 'always' 才会生效.
259
+ // 该配置允许你定义结果标签的格式,该格式的组成是字符串以及可以由方括号包裹字符串作为变量
260
+ // 例如对于 "my-classname--[local]",其中的 [local] 会被替换成相应的变量
261
+ labelFormat?: string,
262
+ // 默认值 undefined.
263
+ // 该配置允许让编译器知道哪一个引入需要进行转换,所以如果你重导出了 emotion
264
+ // 的导出,你仍然可以使用该插件进行转换
265
+ importMap?: {
266
+ [packageName: string]: {
267
+ [exportName: string]: {
268
+ canonicalImport?: [string, string],
269
+ styledBaseImport?: [string, string],
270
+ }
271
+ }
272
+ },
273
+ },
274
+ ```
275
+
276
+ 由 Next.js 团队移植自 [@emotion/babel-plugin](https://www.npmjs.com/package/@emotion/babel-plugin)。
277
+
278
+ #### extensions.pluginImport
279
+
280
+ :::tip
281
+ Builder 提供了 [source.transformImport](/configure/app/source/transform-import) 配置项,因此你不需要手动配置 `extensions.pluginImport`。
282
+ :::
283
+
284
+ 移植自 [babel-plugin-import](https://github.com/umijs/babel-plugin-import),配置选项保持一致。
285
+
286
+ 一些配置可以传入函数,例如 `customName`,`customStyleName` 等,这些 JavaScript 函数会由 Rust 通过 Node-API 调用,这种调用会造成一些性能劣化。
287
+
288
+ 简单的函数逻辑其实可以通过模版语言来代替,因此`customName`,`customStyleName` 等这些配置除了可以传入函数,也可以传入字符串作为模版来代替函数,提高性能。
289
+
290
+ 我们以下面代码为例说明:
291
+
292
+ ```ts
293
+ import { MyButton as Btn } from 'foo';
294
+ ```
295
+
296
+ 添加以下配置:
297
+
298
+ ```ts
299
+ PluginSWC({
300
+ extensions: {
301
+ pluginImport: [
302
+ {
303
+ libraryName: 'foo',
304
+ customName: 'foo/es/{{ member }}',
305
+ },
306
+ ],
307
+ },
308
+ });
309
+ ```
310
+
311
+ 其中的 `{{ member }}` 会被替换为相应的引入成员,转换后:
312
+
313
+ ```ts
314
+ import Btn from 'foo/es/MyButton';
315
+ ```
316
+
317
+ 可以看出配置 `customName: "foo/es/{{ member }}"` 的效果等同于配置 `` customName: (member) => `foo/es/${member}` ``,但是不会有 Node-API 的调用开销。
318
+
319
+ 这里使用到的模版是 [handlebars](https://handlebarsjs.com),模版配置中还内置了一些有用的辅助工具,还是以上面的导入语句为例,配置成:
320
+
321
+ ```ts
322
+ PluginSWC({
323
+ extensions: {
324
+ pluginImport: [
325
+ {
326
+ libraryName: 'foo',
327
+ customName: 'foo/es/{{ kebabCase member }}',
328
+ },
329
+ ],
330
+ },
331
+ });
332
+ ```
333
+
334
+ 会转换成下面的结果:
335
+
336
+ ```ts
337
+ import Btn from 'foo/es/my-button';
338
+ ```
339
+
340
+ 除了 `kebabCase` 以外还有 `camelCase`,`snakeCase`,`upperCase`,`lowerCase` 可以使用。
341
+
342
+ ## 限制
343
+
344
+ 不支持 `@babel/plugin-transform-runtime` 以及其他自定义的 Babel 插件。
package/package.json CHANGED
@@ -15,17 +15,17 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.58.1",
18
+ "version": "2.58.2",
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.58.1"
25
+ "@modern-js/sandpack-react": "2.58.2"
26
26
  },
27
27
  "peerDependencies": {
28
- "@modern-js/builder-doc": "^2.58.1"
28
+ "@modern-js/builder-doc": "^2.58.2"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@rspress/shared": "1.27.0",
@@ -39,7 +39,7 @@
39
39
  "rspress": "1.27.0",
40
40
  "ts-node": "^10.9.1",
41
41
  "typescript": "^5",
42
- "@modern-js/builder-doc": "2.58.1"
42
+ "@modern-js/builder-doc": "2.58.2"
43
43
  },
44
44
  "scripts": {
45
45
  "dev": "rspress dev",
package/rspress.config.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import path from 'path';
2
2
  import { defineConfig } from 'rspress/config';
3
- import { NavItem } from '@rspress/shared';
3
+ import type { NavItem } from '@rspress/shared';
4
4
 
5
5
  const { version } = require('./package.json');
6
6
 
@@ -148,5 +148,5 @@ export default defineConfig({
148
148
  '@site': require('path').resolve(__dirname),
149
149
  },
150
150
  },
151
- }
151
+ },
152
152
  });
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import type React from 'react';
2
2
  import cl from 'classnames';
3
3
  import { withBase } from 'rspress/runtime';
4
4
  import styles from './index.module.scss';
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import type React from 'react';
2
2
  import styles from './index.module.css';
3
3
 
4
4
  export const FeatureLayout: React.FC<{ children: React.ReactNode }> = ({
@@ -103,8 +103,8 @@ export default function Footer() {
103
103
  },
104
104
  ];
105
105
 
106
- const Links = links.map((linkItem, i) => (
107
- <div className={styles.linkWrapper} key={i}>
106
+ const Links = links.map(linkItem => (
107
+ <div className={styles.linkWrapper} key={linkItem.title}>
108
108
  <div className={styles.linkTitle}>{linkItem.title}</div>
109
109
  <ul className={styles.items}>
110
110
  {linkItem.items.map((item, key) => (
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import type React from 'react';
2
2
  import { withBase } from 'rspress/runtime';
3
3
  import styles from './index.module.css';
4
4
 
@@ -1,5 +1,7 @@
1
- import ModernSandpack, { ModernSandpackProps } from '@modern-js/sandpack-react';
2
- import React, { PropsWithChildren } from 'react';
1
+ import ModernSandpack, {
2
+ type ModernSandpackProps,
3
+ } from '@modern-js/sandpack-react';
4
+ import React, { type PropsWithChildren } from 'react';
3
5
  import { useDark, NoSSR } from 'rspress/runtime';
4
6
 
5
7
  import './index.css';
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import type React from 'react';
2
2
  import styles from './index.module.css';
3
3
 
4
4
  interface ITitleProps {
package/src/i18n/zhCN.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { EN_US } from './enUS';
1
+ import type { EN_US } from './enUS';
2
2
 
3
3
  export const ZH_CN: Record<keyof typeof EN_US, string> = {
4
4
  introduction: '介绍',
package/src/index.ts CHANGED
@@ -6,5 +6,4 @@ export default {
6
6
  HomeLayout,
7
7
  };
8
8
 
9
- // eslint-disable-next-line import/export
10
9
  export * from 'rspress/theme';