@rsdoctor/docs 1.5.1 → 1.5.2

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.
@@ -69,12 +69,11 @@ Support for loader analysis for Vue projects has been added in Rsdoctor 0.4.
69
69
 
70
70
  - **Rspack's builtin:lightningcss-loader analysis**: Added support for [builtin:lightningcss-loader](https://rspack.rs/guide/features/builtin-lightningcss-loader#builtin-lightningcss-loader) analysis.
71
71
  - **Performance optimization**:
72
-
73
72
  - Reduced the size of the `@rsdoctor/client` package by 60%, improving page rendering speed.
74
73
 
75
74
  <img
76
75
  src="https://assets.rspack.rs/others/assets/rsdoctor/package-size-diff.png"
77
76
  style={{ width: '60%', margin: 'auto' }}
78
77
  />
79
-
80
- - Reduced third-party dependencies, thereby reducing the total download size during installation.
78
+ - Reduced third-party dependencies, thereby reducing the total download size
79
+ during installation.
@@ -138,3 +138,45 @@ When using Rsdoctor to analyze the compilation time of Rspack projects, you may
138
138
  - Reason: The loader in [CssExtractRspackPlugin](https://rspack.rs/plugins/rspack/css-extract-rspack-plugin) asynchronously calls other loaders during the pitch phase and waits for the callback results after these loaders execute. Therefore, the time taken by CssExtractRspackPlugin actually includes the execution time of other loaders and idle time.
139
139
 
140
140
  <img src="https://assets.rspack.rs/rsdoctor/css-extract-loader.png" />
141
+
142
+ ## Using Rsdoctor with Re.Pack or Custom Bundle Extensions
143
+
144
+ Rsdoctor now supports custom JavaScript bundle file extensions beyond the standard `.js` extension. This is particularly useful for projects like Re.Pack that use `.bundle` extensions.
145
+
146
+ ### Supported Extensions
147
+
148
+ By default, Rsdoctor recognizes the following JavaScript bundle extensions:
149
+
150
+ - `.js` - Standard JavaScript files
151
+ - `.bundle` - Re.Pack and other custom bundlers
152
+
153
+ ### No Configuration Required
154
+
155
+ If your project generates bundle files with a `.bundle` extension (e.g., `main.bundle`, `vendor.bundle`), Rsdoctor will automatically:
156
+
157
+ - Parse and analyze `.bundle` files alongside `.js` files
158
+ - Display `.bundle` files in the Bundle Analyzer Graph
159
+ - Include `.bundle` assets in JavaScript asset statistics
160
+ - Support source map analysis for `.bundle` files
161
+
162
+ ### How It Works
163
+
164
+ The detection logic has been updated in the following areas:
165
+
166
+ 1. **Bundle Parsing**: The `parseBundle` function now accepts both `.js` and `.bundle` extensions when analyzing bundle contents.
167
+ 2. **Asset Filtering**: Asset summary and filtering functions treat `.bundle` files as JavaScript assets.
168
+ 3. **File Type Detection**: All file extension matching utilities include `.bundle` as a recognized JavaScript extension.
169
+
170
+ ### Example Use Case
171
+
172
+ Re.Pack projects typically generate bundles with the `.bundle` extension:
173
+
174
+ ```
175
+ dist/
176
+ ├── index.bundle ← Now supported!
177
+ ├── vendor.bundle ← Now supported!
178
+ ├── styles.css
179
+ └── assets/
180
+ ```
181
+
182
+ Rsdoctor will automatically detect and analyze these `.bundle` files without any additional configuration.
@@ -34,7 +34,8 @@ Please refer to the [Linter Type](#linter-type) in this document for the type de
34
34
  - Clicking the **「Show Relations」** on the far right can view the specific reference chain and the corresponding reference file code position of this third-party package.
35
35
 
36
36
  <img src="https://assets.rspack.rs/others/assets/rsdoctor/bundle-alters-relations.png" />
37
- - Clicking the **「!(exclamation mark)」** icon on the far right can view the specific explanation of the rule for the duplicate third-party package.
37
+ - Clicking the **「!(exclamation mark)」** icon on the far right can view
38
+ the specific explanation of the rule for the duplicate third-party package.
38
39
 
39
40
  <img src="https://assets.rspack.rs/others/assets/rsdoctor/bundle-alters-rule.png" />
40
41
 
@@ -222,6 +223,67 @@ interface Config {
222
223
  }
223
224
  ```
224
225
 
226
+ ### [E1006] Module Mixed Chunks
227
+
228
+ When a module is included in both **initial chunks** and **async chunks**, the same module code is bundled into multiple chunks, increasing output size and potentially affecting first-screen load and cache efficiency.
229
+
230
+ - **Initial chunks**: Chunks loaded with the main entry (e.g. entry points, synchronous `import` in the main bundle).
231
+ - **Async chunks**: Chunks loaded on demand via dynamic `import()` or similar.
232
+
233
+ #### Rule details
234
+
235
+ - In the **「Module Mixed Chunks」** tab of Bundle Alerts, all modules that appear in both initial and async chunks are listed.
236
+ - Each entry shows: module path, **Initial Chunks** list, and **Async Chunks** list, so you can locate duplicated modules.
237
+
238
+ #### Common causes
239
+
240
+ - **Same module referenced in two ways**: The module is both synchronously `import`ed in the main bundle or entry, and dynamically `import()`ed somewhere else, so the bundler emits it in both initial and async chunks.
241
+ - **A file is both an entry and an async chunk**: For example, a utility module is configured as an entry and also `import()`ed in app code, so it appears in the entry’s initial chunk and in a dynamically loaded async chunk.
242
+ - **splitChunks overlapping with entry**: A path is split into an async chunk via `splitChunks` / `chunkSplit`, but that path is also an entry or a main-bundle dependency, leading to mixed chunk types.
243
+
244
+ #### Solutions and recommendations
245
+
246
+ 1. **Use a single import style**
247
+ Prefer one way to reference a module: either all synchronous imports (in initial) or all dynamic `import()` (in async). Avoid having the same file both synchronously imported in the main bundle and dynamically imported elsewhere.
248
+
249
+ 2. **Review entry vs dynamic loading**
250
+ If a file is both an entry and part of an async chunk, either remove one of those usages or treat the file as a shared dependency and extract it into a single shared chunk via build config, so both initial and async chunks reference it instead of duplicating it.
251
+
252
+ 3. **Adjust splitChunks / chunkSplit**
253
+ Check rules for that module path in `optimization.splitChunks` (Rspack/Webpack) or `performance.chunkSplit` (Rsbuild), and avoid the same module being split into both initial and async chunks. Use `chunks: 'async'` or `chunks: 'initial'` where appropriate, or control which chunk type it goes into via `cacheGroups` and `test` / `chunks`.
254
+
255
+ 4. **Trace dependencies**
256
+ From the reported module path and chunk list, search the codebase for references to that module, distinguish sync vs dynamic imports, then converge to a single chunk type or extract a common chunk as above.
257
+
258
+ #### Configuration
259
+
260
+ - **ignore**: Module path patterns to ignore (string match: if the module path contains any of these strings, it is ignored).
261
+
262
+ ```ts
263
+ interface Config {
264
+ /** Module path fragments to ignore */
265
+ ignore: string[];
266
+ }
267
+ ```
268
+
269
+ Configuration example:
270
+
271
+ ```ts
272
+ import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';
273
+
274
+ export default {
275
+ plugin: [
276
+ new RsdoctorRspackPlugin({
277
+ linter: {
278
+ rules: {
279
+ 'module-mixed-chunks': ['Warn', { ignore: ['node_modules/'] }],
280
+ },
281
+ },
282
+ }),
283
+ ],
284
+ };
285
+ ```
286
+
225
287
  ## Linter type
226
288
 
227
289
  - The type definition for the `linter` field is as follows:
@@ -72,12 +72,10 @@ import { Badge } from '@theme';
72
72
  在 Rsdoctor 0.4 版本中支持了 Rspack 的 [builtin:lightningcss-loader](https://rspack.rs/guide/features/builtin-lightningcss-loader#builtin-lightningcss-loader) 分析。
73
73
 
74
74
  - Rsdoctor 自身的性能优化
75
-
76
75
  - 减少了 60% 的 `@rsdoctor/client` 包体积,提高页面渲染速度。
77
76
 
78
77
  <img
79
78
  src="https://assets.rspack.rs/others/assets/rsdoctor/package-size-diff.png"
80
79
  style={{ width: '60%', margin: 'auto' }}
81
80
  />
82
-
83
81
  - 减少 Rsdoctor 可替代的第三方依赖包,从而减少安装时下载总大小。
@@ -138,3 +138,45 @@ export default {
138
138
  - 原因:[CssExtractRspackPlugin](https://rspack.rs/plugins/rspack/css-extract-rspack-plugin) 中的 loader 在 pitch 阶段会异步调用其他 loader,并等待这些 loader 执行后的回调结果。因此,CssExtractRspackPlugin 的耗时实际上包括了其他 loader 的执行时间和空闲时间。
139
139
 
140
140
  <img src="https://assets.rspack.rs/rsdoctor/css-extract-loader.png" />
141
+
142
+ ## 在 Re.Pack 或自定义 Bundle 扩展名项目中使用 Rsdoctor
143
+
144
+ Rsdoctor 现在支持标准 `.js` 扩展名之外的自定义 JavaScript bundle 文件扩展名。这对于使用 `.bundle` 扩展名的 Re.Pack 等项目特别有用。
145
+
146
+ ### 支持的扩展名
147
+
148
+ 默认情况下,Rsdoctor 识别以下 JavaScript bundle 扩展名:
149
+
150
+ - `.js` - 标准 JavaScript 文件
151
+ - `.bundle` - Re.Pack 和其他自定义打包工具
152
+
153
+ ### 无需配置
154
+
155
+ 如果您的项目生成带有 `.bundle` 扩展名的 bundle 文件(例如 `main.bundle`、`vendor.bundle`),Rsdoctor 将自动:
156
+
157
+ - 解析和分析 `.bundle` 文件以及 `.js` 文件
158
+ - 在 Bundle 分析图表中显示 `.bundle` 文件
159
+ - 在 JavaScript 资源统计中包含 `.bundle` 资源
160
+ - 支持 `.bundle` 文件的 source map 分析
161
+
162
+ ### 工作原理
163
+
164
+ 检测逻辑已在以下领域更新:
165
+
166
+ 1. **Bundle 解析**:`parseBundle` 函数现在在分析 bundle 内容时接受 `.js` 和 `.bundle` 扩展名。
167
+ 2. **资源过滤**:资源摘要和过滤函数将 `.bundle` 文件视为 JavaScript 资源。
168
+ 3. **文件类型检测**:所有文件扩展名匹配工具都包含 `.bundle` 作为公认的 JavaScript 扩展名。
169
+
170
+ ### 用例示例
171
+
172
+ Re.Pack 项目通常生成带有 `.bundle` 扩展名的 bundle:
173
+
174
+ ```
175
+ dist/
176
+ ├── index.bundle ← 现已支持!
177
+ ├── vendor.bundle ← 现已支持!
178
+ ├── styles.css
179
+ └── assets/
180
+ ```
181
+
182
+ Rsdoctor 将自动检测和分析这些 `.bundle` 文件,无需任何额外配置。
@@ -219,6 +219,67 @@ interface Config {
219
219
  }
220
220
  ```
221
221
 
222
+ ### [E1006] Module Mixed Chunks
223
+
224
+ 当某个模块同时被包含在 **initial chunks**(初始 chunk)和 **async chunks**(异步 chunk)中时,会导致同一份模块代码被重复打进多个 chunk,增加产物体积,并可能影响首屏加载与缓存效率。
225
+
226
+ - **Initial chunks**:随主入口一起加载的 chunk(如 entry、主包里的同步 import)。
227
+ - **Async chunks**:通过动态 `import()` 等方式按需加载的 chunk。
228
+
229
+ #### 规则详情
230
+
231
+ - 在 Bundle Alerts 的 **「Module Mixed Chunks」** 标签页中,会列出所有同时出现在初始 chunk 与异步 chunk 中的模块。
232
+ - 每个条目会展示:模块路径、所属的 **Initial Chunks** 列表和 **Async Chunks** 列表,便于定位重复打包的模块。
233
+
234
+ #### 常见原因
235
+
236
+ - **同一模块被两种方式引用**:既在主包或 entry 里被同步 `import`,又在某处被动态 `import()` 引用,构建工具会分别打进 initial 与 async chunk。
237
+ - **某文件既作 entry 又作异步 chunk**:例如某工具模块既在配置里被设为 entry,又在业务代码里被 `import()`,会导致该模块同时出现在 entry 产物的 initial chunk 和动态加载的 async chunk 中。
238
+ - **splitChunks 与 entry 重叠**:通过 `splitChunks` / `chunkSplit` 把某路径单独拆成 async chunk,但该路径同时又是 entry 或主包依赖,也会出现混合。
239
+
240
+ #### 解决方案与建议
241
+
242
+ 1. **统一引用方式**
243
+ 尽量对同一模块只使用一种引用方式:要么全部同步 import(放进 initial),要么全部动态 `import()`(放进 async)。避免「主包同步引用 + 某处动态引用」同一文件。
244
+
245
+ 2. **审视 entry 与动态加载**
246
+ 若某文件既作为 entry 又被打进异步 **chunk**,考虑:去掉其中一种用法;或将该文件只作为公共依赖,通过构建配置抽成单一 shared chunk,由 initial 与 async 共同引用,而不是重复打包。
247
+
248
+ 3. **调整 splitChunks / chunkSplit**
249
+ 检查 `optimization.splitChunks`(Rspack/Webpack)或 `performance.chunkSplit`(Rsbuild)中对该模块路径的规则,避免同一模块被同时拆到 initial 与 async 两类 chunk。可适当使用 `chunks: 'async'` 或 `chunks: 'initial'` 做区分,或通过 `cacheGroups` 的 `test` 与 `chunks` 控制其只进入一类 chunk。
250
+
251
+ 4. **梳理依赖关系**
252
+ 根据报告中的模块路径与 chunk 列表,在源码中搜索该模块的引用位置,区分同步与动态引用,再按上述方式收敛为单一 chunk 类型或抽成公共 chunk。
253
+
254
+ #### 配置
255
+
256
+ - **ignore**:配置需要忽略的模块路径(支持字符串匹配:模块路径包含配置中的某字符串即忽略)。
257
+
258
+ ```ts
259
+ interface Config {
260
+ /** 需要忽略的模块路径片段 */
261
+ ignore: string[];
262
+ }
263
+ ```
264
+
265
+ 配置示例:
266
+
267
+ ```ts
268
+ import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';
269
+
270
+ export default {
271
+ plugin: [
272
+ new RsdoctorRspackPlugin({
273
+ linter: {
274
+ rules: {
275
+ 'module-mixed-chunks': ['Warn', { ignore: ['node_modules/'] }],
276
+ },
277
+ },
278
+ }),
279
+ ],
280
+ };
281
+ ```
282
+
222
283
  ## Linter 类型定义
223
284
 
224
285
  - `linter`字段的类型如下:
@@ -13,5 +13,6 @@ Overall 页面中的 `Alerts` 部分用于展示「构建规则」及「编译
13
13
  1. [[E1001] Duplicate Packages](../../guide/rules/rules#e1001-duplicate-packages)
14
14
  2. [[E1002] Cross Chunks Package](../../guide/rules/rules#e1002-cross-chunks-package)
15
15
  3. [[E1004] ECMA Version Check](../../guide/rules/rules#e1004-ecma-version-check)
16
+ 4. [[E1006] Module Mixed Chunks](../../guide/rules/rules#e1006-module-mixed-chunks)
16
17
 
17
18
  具体可以查看[内置规则](../../guide/rules/rules)。
@@ -29,6 +29,7 @@
29
29
  3. [[E1003] Loader Performance Optimization](/guide/rules/rules#e1003-loader-performance-optimization)
30
30
  4. [[E1004] ECMA Version Check](/guide/rules/rules#e1004-ecma-version-check)
31
31
  5. [[E1005] Default Import Check](/guide/rules/rules#e1005-default-import-check)
32
+ 6. [[E1006] Module Mixed Chunks](/guide/rules/rules#e1006-module-mixed-chunks)
32
33
 
33
34
  具体可以查看[内置规则](/guide/rules/rules)。
34
35
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsdoctor/docs",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/web-infra-dev/rsdoctor",
@@ -33,7 +33,7 @@
33
33
  "rspress-plugin-sitemap": "^1.2.1",
34
34
  "typescript": "^5.9.2",
35
35
  "@rsbuild/plugin-sass": "^1.4.1",
36
- "@rsdoctor/types": "1.5.1"
36
+ "@rsdoctor/types": "1.5.2"
37
37
  },
38
38
  "dependencies": {
39
39
  "@rstack-dev/doc-ui": "1.12.3",