@modern-js/main-doc 2.40.0 → 2.42.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. package/docs/en/apis/app/commands.mdx +3 -1
  2. package/docs/en/community/contributing-guide.mdx +10 -0
  3. package/docs/en/configure/app/output/enable-inline-route-manifests.mdx +14 -4
  4. package/docs/en/configure/app/tools/bundler-chain.mdx +0 -4
  5. package/docs/en/guides/advanced-features/build-performance.mdx +156 -0
  6. package/docs/en/guides/advanced-features/optimize-bundle.mdx +115 -0
  7. package/docs/en/guides/advanced-features/rspack-start.mdx +1 -1
  8. package/docs/en/guides/advanced-features/source-build.mdx +161 -0
  9. package/docs/en/guides/advanced-features/testing.mdx +2 -2
  10. package/docs/en/guides/advanced-features/using-storybook.mdx +1 -1
  11. package/docs/en/guides/advanced-features/web-server.mdx +1 -1
  12. package/docs/en/guides/get-started/introduction.mdx +8 -13
  13. package/docs/en/guides/get-started/tech-stack.mdx +1 -1
  14. package/docs/en/guides/troubleshooting/builder.mdx +550 -21
  15. package/docs/en/guides/troubleshooting/hmr.mdx +148 -0
  16. package/docs/zh/apis/app/commands.mdx +3 -1
  17. package/docs/zh/community/contributing-guide.mdx +10 -0
  18. package/docs/zh/configure/app/output/enable-inline-route-manifests.mdx +6 -6
  19. package/docs/zh/configure/app/tools/bundler-chain.mdx +0 -4
  20. package/docs/zh/guides/advanced-features/build-performance.mdx +156 -0
  21. package/docs/zh/guides/advanced-features/optimize-bundle.mdx +115 -0
  22. package/docs/zh/guides/advanced-features/rspack-start.mdx +1 -1
  23. package/docs/zh/guides/advanced-features/source-build.mdx +161 -0
  24. package/docs/zh/guides/advanced-features/testing.mdx +1 -1
  25. package/docs/zh/guides/advanced-features/using-storybook.mdx +1 -1
  26. package/docs/zh/guides/advanced-features/web-server.mdx +1 -1
  27. package/docs/zh/guides/get-started/introduction.mdx +8 -15
  28. package/docs/zh/guides/get-started/tech-stack.mdx +1 -1
  29. package/docs/zh/guides/topic-detail/generator/plugin/structure.md +1 -1
  30. package/docs/zh/guides/troubleshooting/builder.mdx +553 -20
  31. package/docs/zh/guides/troubleshooting/hmr.mdx +148 -0
  32. package/package.json +8 -8
  33. package/rspress.config.ts +8 -4
  34. package/src/components/SolutionCards/index.module.scss +4 -0
  35. package/src/components/SolutionCards/index.tsx +5 -1
  36. package/src/pages/index.tsx +0 -10
@@ -7,7 +7,7 @@ sidebar_position: 1
7
7
 
8
8
  **Modern.js 是字节跳动 Web 工程体系的开源版本**,它提供多个解决方案,来帮助开发者解决不同研发场景下的问题。
9
9
 
10
- 目前 Modern.js 包含三个解决方案,分别面向 Web 应用开发场景、npm 包开发场景和 Web 应用构建场景:
10
+ 目前 Modern.js 包含两个解决方案,分别面向 Web 应用开发场景 npm 包开发场景:
11
11
 
12
12
  import { SolutionCards } from '@site/src/components/SolutionCards';
13
13
 
@@ -23,32 +23,21 @@ import { SolutionCards } from '@site/src/components/SolutionCards';
23
23
  description: '易用、高性能的 npm 包开发方案',
24
24
  link: 'http://modernjs.dev/module-tools/',
25
25
  },
26
- {
27
- title: 'Modern.js Builder',
28
- description: '基于 Rspack 的 Web 构建工具',
29
- link: 'http://modernjs.dev/builder/',
30
- },
31
26
  ]}
32
27
  />
33
28
 
34
- 作为 Modern.js 工程体系的一部分,以上每个解决方案都可以被单独使用,并且各自部署了独立的文档站点。开发者可以按需选择其中的一个或多个解决方案来使用。
35
-
36
29
  ## 关于文档
37
30
 
38
31
  **当前文档站对应的是 Modern.js 框架**,适用于开发 Web 应用。
39
32
 
40
- - 如果你需要开发一个 npm 包,请移步 [Modern.js Module](https://modernjs.dev/module-tools) 文档。
41
- - 如果你需要基于 Modern.js 的构建工具来实现一个 Web 开发框架,请移步 [Modern.js Builder](https://modernjs.dev/builder) 文档。
33
+ - 如果你需要开发一个 npm 包,请移步 [Modern.js Module 文档](https://modernjs.dev/module-tools)
34
+ - 如果你需要一个构建工具来打包 Web 应用,请移步 [Rsbuild 文档](https://rsbuild.dev/)
35
+ - 如果你需要开发一个文档站点,推荐使用 [Rspress 文档](https://rspress.dev/)。
42
36
 
43
37
  :::tip
44
38
  由于 Modern.js 框架的使用最为广泛,在本文档站中,我们会省略「框架」,直接称其为 Modern.js。
45
39
  :::
46
40
 
47
- Modern.js 也可以与以下解决方案结合使用:
48
-
49
- - 如果你需要开发一个文档站点,推荐使用 [Rspress](https://rspress.dev/) 文档。
50
- - 如果你需要引入微前端架构,推荐使用 [Garfish](https://garfishjs.org/)。
51
-
52
41
  ## Modern.js 框架
53
42
 
54
43
  **Modern.js 框架是一个基于 React 的渐进式 Web 开发框架**。在字节跳动内部,我们将 Modern.js 封装为上层框架,并支撑了数千个 Web 应用的研发。
@@ -86,6 +75,10 @@ Umi 是中文社区中非常流行的 React 框架,也是蚂蚁集团的底层
86
75
 
87
76
  此外,Modern.js 的服务端能力更加丰富,包括完备的 SSR 能力、一体化 BFF 开发能力和自定义 Web Server 支持。这些能力经过了字节跳动大量线上应用的验证,可以直接用于生产环境。
88
77
 
78
+ ### Remix
79
+
80
+ 请参考 [Modern.js vs Remix](https://github.com/web-infra-dev/modern.js/discussions/4872)。
81
+
89
82
  ## 下一步
90
83
 
91
84
  如果你希望了解如何使用 Modern.js 框架,可以尝试 [创建第一个应用](/tutorials/first-app/c01-start),或是阅读 [快速上手](/guides/get-started/quick-start)。
@@ -14,7 +14,7 @@ Modern.js 框架默认集成了一些社区中流行的库和开发工具。
14
14
 
15
15
  Modern.js 使用 [React 18](https://react.dev/) 来构建用户界面,同时也兼容 React 17。
16
16
 
17
- Modern.js 底层的 Builder 也支持构建 Vue 应用,如果你需要使用 Vue,可以参考[「构建 Vue 应用」](https://modernjs.dev/builder/guide/framework/vue3.html)。
17
+ Modern.js 底层的 Rsbuild 支持构建 Vue 应用,如果你需要使用 Vue,可以参考[「Rsbuild - Vue](https://rsbuild.dev/zh/guide/framework/vue3)。
18
18
 
19
19
  ---
20
20
 
@@ -99,7 +99,7 @@ export default function (context: IPluginContext) {
99
99
 
100
100
  ## templates
101
101
 
102
- `templates` 目录存在当前定制化方式的模板文件,支持 [Handlebars](https://handlebarsjs.com/) 和 [EJS](https://ejs.co/) 格式,将根据模板文件后缀使用不同的渲染引擎就行渲染,如果无后缀,将会直接复制模板文件到目标目录。
102
+ `templates` 目录存在当前定制化方式的模板文件,支持 [Handlebars](https://handlebarsjs.com/) 和 [EJS](https://ejs.co/) 格式,将根据模板文件后缀使用不同的渲染引擎执行渲染,如果无后缀,将会直接复制模板文件到目标目录。
103
103
 
104
104
  如果模板文件为 `js`、`ts` 或者 `json` 文件,推荐直接使用 `.handlebars` 或者 `.ejs` 后缀,可避免项目 eslint 报错和在 Monorepo 中项目识别问题。
105
105
 
@@ -6,34 +6,567 @@ sidebar_position: 3
6
6
 
7
7
  如果你遇到了构建相关的问题,可以参考以下文档:
8
8
 
9
- ## 通用类问题
9
+ ### 如何配置组件库按需引入?
10
10
 
11
- 请参考 [「Modern.js Builder - 通用类问题」](https://modernjs.dev/builder/guide/faq/general.html),其中包含一些概念类的通用问题,比如:
11
+ 如果需要配置组件库的按需引入,你可以通过 [source.transformImport](/configure/app/source/transform-import.html) 配置,这个配置的能力等价于 [babel-plugin-import](https://www.npmjs.com/package/babel-plugin-import)
12
12
 
13
- - Modern.js Builder 和 Modern.js 的关系?
14
- - Builder 能否用于构建工具库或组件库?
15
- - Builder 是否会接入 Vite?
13
+ ```ts
14
+ export default {
15
+ source: {
16
+ transformImport: [
17
+ {
18
+ libraryName: 'xxx-components',
19
+ libraryDirectory: 'es',
20
+ style: true,
21
+ },
22
+ ],
23
+ },
24
+ };
25
+ ```
16
26
 
17
- ## 功能类问题
27
+ ---
28
+
29
+ ### 如何在编译过程中进行 ESLint 代码校验?
30
+
31
+ 出于编译性能的考虑,Modern.js 默认不会在编译过程中进行 ESLint 校验,如果需要该功能,可以手动安装并注册社区中的 [eslint-webpack-plugin](https://github.com/webpack-contrib/eslint-webpack-plugin)。
32
+
33
+ 注册该插件的示例代码如下:
34
+
35
+ ```js
36
+ import ESLintPlugin from 'eslint-webpack-plugin';
37
+
38
+ export default {
39
+ tools: {
40
+ bundlerChain(chain) {
41
+ chain.plugin('eslint-plugin').use(ESLintPlugin, [
42
+ {
43
+ extensions: ['.js', '.ts', '.jsx', 'tsx', '.mjs'],
44
+ },
45
+ ]);
46
+ },
47
+ },
48
+ };
49
+ ```
50
+
51
+ > 更详细的用法请参考 [eslint-webpack-plugin](https://github.com/webpack-contrib/eslint-webpack-plugin) 文档。
52
+
53
+ ---
54
+
55
+ ### 如何配置静态资源的 CDN 路径?
56
+
57
+ 如果需要将 JS、CSS 等静态资源上传到 CDN 使用,那么可以通过 [output.assetPrefix](/configure/app/output/asset-prefix.html) 配置来设置静态资源的 URL 前缀。
58
+
59
+ ```js
60
+ export default {
61
+ output: {
62
+ assetPrefix: 'https://cdn.example.com/assets/',
63
+ },
64
+ };
65
+ ```
66
+
67
+ ---
68
+
69
+ ### 如何清空 webpack 编译缓存?
70
+
71
+ 默认情况下,Modern.js 的 webpack 编译缓存生成在 `./node_modules/.cache/webpack` 目录下。
72
+
73
+ 如果需要清空本地的编译缓存,可以执行以下命令:
74
+
75
+ ```bash
76
+ rm -rf ./node_modules/.cache
77
+ ```
78
+
79
+ ---
80
+
81
+ ### 如何移除代码中的 console?
82
+
83
+ 在生产环境构建时,我们可以移除代码中的 `console`,从而避免开发环境的日志被输出到生产环境。
84
+
85
+ Modern.js 默认提供了移除 console 的配置项,请查看 [performance.removeConsole](/configure/app/performance/remove-console.html)。
86
+
87
+ ---
88
+
89
+ ### 如何查看最终生成的 webpack / Rspack 配置?
90
+
91
+ Modern.js 提供 [inspect 命令](/apis/app/commands.html) 用于查看项目最终生成的 Modern.js 配置以及 webpack / Rspack 配置。
92
+
93
+ ```bash
94
+ ➜ npx modern inspect
95
+
96
+ Inspect config succeed, open following files to view the content:
97
+
98
+ - Builder Config: /root/my-project/dist/builder.config.js
99
+ - Rspack Config (web): /root/my-project/dist/rspack.config.web.js
100
+ ```
101
+
102
+ ---
103
+
104
+ ### 如何忽略特定 warning 日志?
105
+
106
+ 默认情况下,Modern.js 会打印构建过程产生的所有 error 和 warning 日志。
107
+
108
+ 如果遇到由于三方包产生大量 warning 日志,暂时又无法处理,希望忽略的情况。可通过 webpack / Rspack 提供的构建配置忽略特定 warning 日志。
109
+
110
+ ```ts
111
+ export default {
112
+ tools: {
113
+ bundlerChain: chain => {
114
+ chain.ignoreWarnings([/Using \/ for division outside of calc()/]);
115
+ },
116
+ },
117
+ };
118
+ ```
119
+
120
+ 详细信息可参考: [ignoreWarnings](https://webpack.js.org/configuration/other-options/#ignorewarnings)。
121
+
122
+ ---
123
+
124
+ ### webpack 编译出现 'compilation' argument 报错?
125
+
126
+ 如果编译时出现以下报错,通常是由于项目中安装了错误的 webpack 版本,或者安装了多个 webpack 版本引起:
127
+
128
+ ```bash
129
+ TypeError: The 'compilation' argument must be an instance of Compilation
130
+ ```
131
+
132
+ webpack 版本问题有以下几种情况:
133
+
134
+ 1. 项目的 package.json 中直接声明了 webpack 依赖,并且与 Modern.js 依赖的 webpack 版本范围不同,无法匹配到同一个版本。
135
+ 2. 项目里安装的多个 npm 包都依赖了 webpack,并且它们依赖的 webpack 版本范围不同,无法匹配到同一个版本。
136
+ 3. 由于包管理器的 lock 机制,导致 lock 文件中产生了多个 webpack 版本。
137
+
138
+ 如果是第一种情况,建议从项目的 package.json 中移除 webpack 依赖。因为 Modern.js 默认封装了 webpack 相关能力,并且会在 [tools.webpack](/configure/app/tools/webpack.html) 配置项中传入 webpack 对象。因此在大多数情况下,不建议在项目中额外安装 webpack 依赖。
139
+
140
+ 如果是第二种情况,建议看看能否升级某个 npm 包,使其依赖的 webpack 版本范围与 Modern.js 保持一致。也可以通过包管理器的能力来手动统一版本,比如使用 [yarn resolutions](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/) 或 [pnpm overrides](https://pnpm.io/package_json#pnpmoverrides)。
141
+
142
+ 如果是第三种情况,可以使用第二种情况中提到的两种方法,也可以尝试删除 lock 文件后重新安装来解决。
143
+
144
+ :::tip
145
+ 删除 lock 文件会使项目中的依赖版本自动升级到指定范围下的最新版,请进行充分的测试。
146
+ :::
147
+
148
+ ---
149
+
150
+ ### 编译产物中存在未编译的 ES6+ 代码?
151
+
152
+ 默认情况下,Modern.js 不会通过 `babel-loader` 或 `ts-loader` 来编译 `node_modules` 下的文件。如果项目引入的 npm 包中含有 ES6+ 语法,会被打包进产物中。
153
+
154
+ 遇到这种情况时,可以通过 [source.include](/configure/app/source/include.html) 配置项来指定需要额外进行编译的目录或模块。
155
+
156
+ ---
157
+
158
+ ### 在 Monorepo 中引用其他模块,代码没有被正确编译?
159
+
160
+ 出于编译性能的考虑,默认情况下,Modern.js 不会编译 `node_modules` 下的文件,也不会编译当前工程目录外部的文件。
161
+
162
+ 因此,当你引用其他子项目的源代码时,可能会遇到类似 `You may need an additional loader to handle the result of these loaders.` 的报错。
163
+
164
+ 这个问题有以下解决方法:
165
+
166
+ 1. 你可以开启源码构建模式来编译 monorepo 中的其他子项目,参考[「源码构建模式」](/guides/advanced-features/source-build.html)。
167
+ 2. 你可以添加 `source.include` 配置项,指定需要额外进行编译的目录或模块,参考 [source.include 用法介绍](/configure/app/source/include.html)。
168
+ 3. 你可以预先构建需要引用的子项目,生成对应的构建产物,并在当前项目引用构建产物,而不是引用源代码。
169
+
170
+ ---
171
+
172
+ ### 编译时报错 `You may need additional loader`?
173
+
174
+ 如果编译过程中遇到了以下报错提示,表示存在个别文件无法被正确编译。
175
+
176
+ ```bash
177
+ Module parse failed: Unexpected token
178
+ File was processed with these loaders:
179
+ * some-loader/index.js
180
+
181
+ You may need an additional loader to handle the result of these loaders.
182
+ ```
183
+
184
+ 解决方法:
185
+
186
+ - 如果是引用了当前工程外部的 `.ts` 文件,或者是 node_modules 下的 `.ts` 文件,请添加 [source.include](/configure/app/source/include.html) 配置项,指定需要额外进行编译的文件。
187
+ - 如果是引用了 Modern.js 不支持的文件格式,请自行配置对应的 webpack loader 进行编译。
188
+
189
+ ---
190
+
191
+ ### 编译时报错 `Error: [object Object] is not a PostCSS plugin` ?
192
+
193
+ 目前,Modern.js 使用的是 v8 版本的 PostCSS。如果编译过程中遇到了 `Error: [object Object] is not a PostCSS plugin` 报错提示,通常是由于引用到了错误的 PostCSS 版本导致,常见的如 `cssnano` 中 `postcss` (peerDependencies) 版本不符合预期。
194
+
195
+ 可以通过 `npm ls postcss` 查找 `UNMET PEER DEPENDENCY` 的依赖,然后在 package.json 中通过指定 PostCSS 版本等方式安装正确的依赖版本即可。
196
+
197
+ ```
198
+ npm ls postcss
199
+
200
+ ├─┬ css-loader@6.3.0
201
+ │ └── UNMET PEER DEPENDENCY postcss@8.3.9
202
+ ├─┬ css-minimizer-webpack-plugin@3.0.0
203
+ │ └── UNMET PEER DEPENDENCY postcss@8.3.9
204
+ ```
205
+
206
+ ---
207
+
208
+ ### 打开页面后报错,提示 exports is not defined?
209
+
210
+ 如果编译正常,但是打开页面后出现 `exports is not defined` 报错,通常是因为在项目中使用 Babel 编译了一个 CommonJS 模块,导致 Babel 出现异常。
211
+
212
+ 在正常情况下,Modern.js 是不会使用 Babel 来编译 CommonJS 模块的。如果项目中使用了 [source.include](/configure/app/source/include.html) 配置项,则可能会把一些 CommonJS 模块加入到 Babel 编译中。
213
+
214
+ 该问题有两种解决方法:
215
+
216
+ 1. 避免将 CommonJS 模块加入到 Babel 编译中。
217
+ 2. 将 Babel 的 `sourceType` 配置项设置为 `unambiguous`,示例如下:
218
+
219
+ ```js
220
+ export default {
221
+ tools: {
222
+ babel(config) {
223
+ config.sourceType = 'unambiguous';
224
+ },
225
+ },
226
+ };
227
+ ```
228
+
229
+ 将 `sourceType` 设置为 `unambiguous` 可能会产生一些其他影响,请参考 [Babel 官方文档](https://babeljs.io/docs/en/options#sourcetype)。
230
+
231
+ ---
232
+
233
+ ### 编译时报错 "Error: ES Modules may not assign module.exports or exports.\*, Use ESM export syntax"?
234
+
235
+ 如果编译时出现以下报错,通常也是因为在项目中使用 Babel 编译了一个 CommonJS 模块,解决方法与上述的 `exports is not defined` 问题一致。
236
+
237
+ ```bash
238
+ Error: ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: 581
239
+ ```
240
+
241
+ 更多信息请参考 issue:[babel#12731](https://github.com/babel/babel/issues/12731)。
242
+
243
+ ---
18
244
 
19
- 请参考 [「Modern.js Builder - 功能类问题」](https://modernjs.dev/builder/guide/faq/features.html),其中包含一些常见构建功能的介绍,比如:
245
+ ### 编译时报错 "export 'foo' (imported as 'foo') was not found in './utils'"?
20
246
 
21
- - 如何配置组件库按需引入?
22
- - 如何在编译过程中进行 ESLint 代码校验?
23
- - 如何配置静态资源的 CDN 路径?
247
+ 如果编译的过程中出现此报错,说明代码中引用了一个不存在的导出。
24
248
 
25
- ## 异常类问题
249
+ 比如以下例子,`index.ts` 中引用了 `utils.ts` 中的 `foo` 变量, 但 `utils.ts` 实际上只导出了 `bar` 变量。
26
250
 
27
- 请参考 [「Modern.js Builder - 异常类问题」](https://modernjs.dev/builder/guide/faq/exceptions.html),其中包含一些常见构建问题的处理方法,比如:
251
+ ```ts
252
+ // utils.ts
253
+ export const bar = 'bar';
254
+
255
+ // index.ts
256
+ import { foo } from './utils';
257
+ ```
258
+
259
+ 在这种情况下,Modern.js 会抛出以下错误:
260
+
261
+ ```bash
262
+ Compile Error:
263
+ File: ./src/index.ts
264
+ export 'foo' (imported as 'foo') was not found in './utils' (possible exports: bar)
265
+ ```
266
+
267
+ 当你遇到该问题时,首先需要检查相关代码里 import / export 的内容是否正确,并修正相关错误。
268
+
269
+ 常见的错误写法有:
270
+
271
+ - 引入了不存在的变量:
272
+
273
+ ```ts
274
+ // utils.ts
275
+ export const bar = 'bar';
276
+
277
+ // index.ts
278
+ import { foo } from './utils';
279
+ ```
280
+
281
+ - re-export 了一个类型,但是没有添加 `type` 修饰符,导致 babel 等编译工具无法识别到类型导出,导致编译异常。
282
+
283
+ ```ts
284
+ // utils.ts
285
+ export type Foo = 'bar';
286
+
287
+ // index.ts
288
+ export { Foo } from './utils'; // 错误写法
289
+ export type { Foo } from './utils'; // 正确写法
290
+ ```
291
+
292
+ 在个别情况下,以上报错是由第三方依赖引入的,你无法直接修改它。此时,如果你确定该问题不影响你的应用,那么可以添加以下配置,将 `error` 日志修改为 `warn` 级别:
293
+
294
+ ```ts
295
+ export default {
296
+ tools: {
297
+ webpackChain(chain) {
298
+ chain.module.parser.merge({
299
+ javascript: {
300
+ exportsPresence: 'warn',
301
+ },
302
+ });
303
+ },
304
+ },
305
+ };
306
+ ```
307
+
308
+ 同时,你需要尽快联系第三方依赖的开发者来修复相应的问题。
309
+
310
+ > 你可以查看 webpack 的文档来了解 [module.parser.javascript.exportsPresence](https://webpack.js.org/configuration/module/#moduleparserjavascriptexportspresence) 的更多细节。
311
+
312
+ ---
313
+
314
+ ### 编译进度条卡死,但终端无 Error 日志?
315
+
316
+ 当编译进度条卡死,但终端无 Error 日志时,通常是因为编译过程中出现了异常。在某些情况下,当 Error 被 webpack 或其他模块捕获后,错误日志不会被正确输出。最为常见的场景是 Babel 配置出现异常,抛出 Error 后被 webpack 捕获,而 webpack 在个别情况下吞掉了 Error。
317
+
318
+ **解决方法:**
319
+
320
+ 如果你修改 Babel 配置后出现此问题,建议检查是否有以下错误用法:
321
+
322
+ 1. 配置了一个不存在的 plugin 或 preset,可能是名称拼写错误,或是未正确安装。
323
+
324
+ ```ts
325
+ // 错误示例
326
+ export default {
327
+ tools: {
328
+ babel(config, { addPlugins }) {
329
+ // 该插件名称错误,或者未安装
330
+ addPlugins('babel-plugin-not-exists');
331
+ },
332
+ },
333
+ };
334
+ ```
335
+
336
+ 2. 是否配置了多个 babel-plugin-import,但是没有在数组的第三项声明每一个 babel-plugin-import 的名称。
337
+
338
+ ```ts
339
+ // 错误示例
340
+ export default {
341
+ tools: {
342
+ babel(config, { addPlugins }) {
343
+ addPlugins([
344
+ [
345
+ 'babel-plugin-import',
346
+ { libraryName: 'antd', libraryDirectory: 'es' },
347
+ ],
348
+ [
349
+ 'babel-plugin-import',
350
+ { libraryName: 'antd-mobile', libraryDirectory: 'es' },
351
+ ],
352
+ ]);
353
+ },
354
+ },
355
+ };
356
+ ```
357
+
358
+ ```ts
359
+ // 正确示例
360
+ export default {
361
+ tools: {
362
+ babel(config, { addPlugins }) {
363
+ addPlugins([
364
+ [
365
+ 'babel-plugin-import',
366
+ { libraryName: 'antd', libraryDirectory: 'es' },
367
+ 'antd',
368
+ ],
369
+ [
370
+ 'babel-plugin-import',
371
+ { libraryName: 'antd-mobile', libraryDirectory: 'es' },
372
+ 'antd-mobile',
373
+ ],
374
+ ]);
375
+ },
376
+ },
377
+ };
378
+ ```
379
+
380
+ 除了上述原因外,还有一种可能会导致 Babel 编译卡死,就是使用 Babel 编译了一个超过 1 万行的大型 JS 文件(通常是使用 `source.include` 编译了 node_modules 中的某个大文件)。
381
+
382
+ 当 Babel 编译大文件时,Modern.js 内置的 babel-plugin-styled-components 会卡死,社区中已有 [相关 issue](https://github.com/styled-components/babel-plugin-styled-components/issues/374)。
383
+
384
+ 未来 Modern.js 会考虑移除内置的 babel-plugin-styled-components。在当前版本里,你可以将 [tools.styledComponents](/configure/app/tools/styled-components.html) 设置为 `false` 来移除该插件。
385
+
386
+ ```ts title="modern.config.ts"
387
+ export default {
388
+ tools: {
389
+ styledComponents: false,
390
+ },
391
+ };
392
+ ```
393
+
394
+ ---
395
+
396
+ ### webpack 编译缓存未生效,应该如何排查?
397
+
398
+ Modern.js 默认开启了 webpack 的持久化缓存。
399
+
400
+ 首次编译完成后,会自动生成缓存文件,并输出到 `./node_modules/.cache/webpack` 目录下。执行第二次编译时,会命中缓存,并大幅度提高编译速度。
401
+
402
+ 当 `package.json` 等配置文件被修改时,缓存会自动失效。
403
+
404
+ 如果项目中 webpack 编译缓存一直未生效,可以添加以下配置进行排查:
405
+
406
+ ```ts
407
+ export default {
408
+ tools: {
409
+ webpack(config) {
410
+ config.infrastructureLogging = {
411
+ ...config.infrastructureLogging,
412
+ debug: /webpack\.cache/,
413
+ };
414
+ },
415
+ },
416
+ };
417
+ ```
418
+
419
+ 添加以上配置后,webpack 会输出日志用于 debug,请参考 `PackFileCacheStrategy` 相关的日志来了解缓存失效的原因。
420
+
421
+ ---
422
+
423
+ ### 打包后发现 tree shaking 没有生效?
424
+
425
+ Modern.js 在生产构建时会默认开启 webpack 的 tree shaking 功能,tree shaking 是否能够生效,取决于业务代码能否满足 webpack 的 tree shaking 条件。
426
+
427
+ 如果你遇到了 tree shaking 不生效的问题,可以检查下相关 npm 包的 `sideEffects` 配置是否正确,如果你不了解 `sideEffects` 的作用,或是对 tree shaking 背后的原理感兴趣,可以阅读以下两篇文档:
428
+
429
+ - [webpack 官方文档 - Tree Shaking](https://webpack.docschina.org/guides/tree-shaking/)
430
+ - [Tree Shaking 问题排查指南](https://bytedance.feishu.cn/docs/doccn8E1ldDct5uv1EEDQs8Ycwe)
431
+
432
+ 如果你是 npm 包的开发者,可以阅读这篇文章:
433
+
434
+ - [如何编写一个友好支持 Tree-shaking 的库](https://zhuanlan.zhihu.com/p/594124786)
435
+
436
+ ---
437
+
438
+ ### 打包时出现 JavaScript heap out of memory?
439
+
440
+ 该报错表示打包过程中出现了内存溢出问题,大多数情况下是由于打包的内容较多,超出了 Node.js 默认的内存上限。
441
+
442
+ 如果出现 OOM 问题,最简单的方法是通过增加内存上限来解决,Node.js 提供了 `--max-old-space-size` 选项来对此进行设置。你可以在 CLI 命令前添加 [NODE_OPTIONS](https://nodejs.org/api/cli.html#node_optionsoptions) 来设置此参数。
443
+
444
+ 比如,在 `modern build` 命令前添加参数:
445
+
446
+ ```diff title="package.json"
447
+ {
448
+ "scripts": {
449
+ - "build": "modern build"
450
+ + "build": "NODE_OPTIONS=--max_old_space_size=16384 modern build"
451
+ }
452
+ }
453
+ ```
454
+
455
+ 如果你执行的是其他命令,比如 `modern deploy`,请在对应的命令前添加参数。
456
+
457
+ `max_old_space_size` 参数的值代表内存上限大小(MB),一般情况下设置为 `16384`(16GB)即可。
458
+
459
+ Node.js 官方文档中有对以下参数更详细的解释:
460
+
461
+ - [NODE_OPTIONS](https://nodejs.org/api/cli.html#node_optionsoptions)
462
+ - [--max-old-space-size](https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes)
463
+
464
+ 除了增加内存上限,通过开启一些编译策略来提升构建效率也是一个解决方案,请参考 [提升构建性能](/guides/advanced-features/build-performance.html)。
465
+
466
+ 如果以上方式无法解决你的问题,可能是项目中某些异常逻辑导致了内存非正常溢出。你可以排查近期的代码变更,定位问题的根因。如果无法定位,请联系我们进行排查。
467
+
468
+ ---
469
+
470
+ ### 打包时出现 Can't resolve 'core-js/modules/xxx.js'?
471
+
472
+ 如果你在打包时出现了类似下面的报错,表示项目中的 [core-js](https://github.com/zloirock/core-js) 无法被正确引用。
473
+
474
+ ```text
475
+ Module not found: Can't resolve 'core-js/modules/es.error.cause.js'
476
+ ```
477
+
478
+ 通常来说,你无须在项目中安装 `core-js`,因为 Modern.js 已经内置了一份 `core-js` v3。
479
+
480
+ 如果出现 `core-js` 找不到的报错,可能有以下几个原因:
481
+
482
+ 1. 项目里覆盖了 Babel 配置的 `plugins`,导致内置的 `babelPluginLockCorejsVersion` 无法正确生效。这种情况将 `tools.babel` 更改为函数用法即可:
483
+
484
+ ```ts
485
+ // 错误用法,会覆盖 Modern.js 默认的 Babel 插件
486
+ export default {
487
+ tools: {
488
+ babel: {
489
+ plugins: ['babel-plugin-xxx'],
490
+ },
491
+ },
492
+ };
493
+
494
+ // 正确用法,在默认配置中新增一个插件,而非覆盖插件
495
+ export default {
496
+ tools: {
497
+ babel(config) {
498
+ config.plugins.push('babel-plugin-xxx');
499
+ },
500
+ },
501
+ };
502
+ ```
503
+
504
+ 2. 项目里某一处代码依赖了 `core-js` v2 版本。这种情况通常需要你找出对应的代码,并升级其中的 `core-js` 到 v3 版本。
505
+ 3. `node_modules` 中的某一个 npm 包引用了 `core-js`,但是没有在 `dependencies` 中声明 `core-js` 依赖。这种情况需要你在对应的 npm 包中声明 `core-js` 依赖,或者在项目根目录下安装一份 `core-js`。
506
+
507
+ ---
508
+
509
+ ### 从 lodash 中引用类型后出现编译报错?
510
+
511
+ 当你的项目中安装了 `@types/lodash` 包时,你可能会从 `lodash` 中引用一些类型,比如引用 `DebouncedFunc` 类型:
512
+
513
+ ```ts
514
+ import { debounce, DebouncedFunc } from 'lodash';
515
+ ```
516
+
517
+ 上述代码会在编译后产生如下报错:
518
+
519
+ ```bash
520
+ SyntaxError: /project/src/index.ts: The 'lodash' method `DebouncedFunc` is not a known module.
521
+ Please report bugs to https://github.com/lodash/babel-plugin-lodash/issues.
522
+ ```
523
+
524
+ 这个问题的原因是 Modern.js 默认开启了 [babel-plugin-lodash](https://github.com/lodash/babel-plugin-lodash) 插件来优化 lodash 产物体积,但 Babel 无法区别「值」和「类型」,导致编译后的代码出现异常。
525
+
526
+ 解决方法是使用 TypeScript 的 `import type` 语法,对 `DebouncedFunc` 类型进行显式声明:
527
+
528
+ ```ts
529
+ import { debounce } from 'lodash';
530
+ import type { DebouncedFunc } from 'lodash';
531
+ ```
532
+
533
+ :::tip
534
+ 在任意情况下,我们都推荐使用 `import type` 来引用类型,这对于编译器识别类型会有很大帮助。
535
+ :::
536
+
537
+ ---
538
+
539
+ ### Less 文件中的除法不生效?
540
+
541
+ Less v4 版本与 v3 版本相比,除法的写法有一些区别:
542
+
543
+ ```less
544
+ // Less v3
545
+ .math {
546
+ width: 2px / 2; // 1px
547
+ width: 2px ./ 2; // 1px
548
+ width: (2px / 2); // 1px
549
+ }
550
+
551
+ // Less v4
552
+ .math {
553
+ width: 2px / 2; // 2px / 2
554
+ width: 2px ./ 2; // 1px
555
+ width: (2px / 2); // 1px
556
+ }
557
+ ```
558
+
559
+ Modern.js 内置的 Less 版本为 v4,低版本的写法不会生效,请注意区分。
560
+
561
+ Less 中除法的写法也可以通过配置项来修改,详见 [Less - Math](https://lesscss.org/usage/#less-options-math)。
562
+
563
+ ---
28
564
 
29
- - webpack 编译出现 'compilation' argument 报错?
30
- - 编译时报错 `You may need additional loader`?
31
- - 打开页面后报错,提示 `exports is not defined`?
565
+ ### 修改配置后,报错 ‘TypeError: Cannot delete property 'xxx' of #\<Object\>’
32
566
 
33
- ## 热更新问题
567
+ 该报错表示在编译过程中对一个只读配置项进行了删除操作。通常情况下,我们不希望编译过程中的任何操作会直接对传入的配置进行修改,但难以限制底层插件(如 postcss-loader 等)的行为,如果出现该报错,请联系 Modern.js 开发者,我们需要对该配置进行单独处理。
34
568
 
35
- 请参考 [「Modern.js Builder - 热更新问题」](https://modernjs.dev/builder/guide/faq/hmr.html),比如:
569
+ 同类型报错还有:
36
570
 
37
- - 打包时 external React 后,热更新不生效?
38
- - 开发环境设置文件名的 hash 后,热更新不生效?
39
- - React 组件的热更新无法生效?
571
+ - 'TypeError: Cannot add property xxx, object is not extensible'
572
+ - 'TypeError: Cannot assign to read only property 'xxx' of object '#\<Object\>'