Skip to content

Commit a8ec465

Browse files
committed
perf: build perf
1 parent 8f08eec commit a8ec465

File tree

3 files changed

+141
-13
lines changed

3 files changed

+141
-13
lines changed

docs/build-and-bundle-optimizations.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,141 @@
8484
- **Mermaid**:
8585
- **问题**:直接 `import('mermaid')` 会引入依赖 `import.meta.url` 的源码,导致 Webpack 构建警告或运行时错误。
8686
- **解决方案**:强制引入预编译的 UMD/Minified 版本:
87+
8788
```javascript
8889
import('mermaid/dist/mermaid.min.js')
8990
```
91+
9092
- **Remark/Rehype 插件**:
9193
- **问题**:在生产模式下,动态导入的插件可能被包装为 Module Namespace 对象(`{ default: fn, ... }`),直接作为函数调用会导致崩溃。
9294
- **解决方案**:在使用前进行兼容性解包:
95+
9396
```javascript
9497
const plugin = importedPlugin?.default || importedPlugin;
9598
```
9699

100+
## 本次构建体积分布(2026-03-09
101+
102+
本节基于以下命令的实际产物与 stats 分析:
103+
104+
```bash
105+
SKIP_OPTIMIZE_MEDIA=1 npm run build:production
106+
```
107+
108+
### 主要超大产物
109+
110+
- `dist/static/js/app.*.js`:约 5.0 MiB(gzip 后约 1.5 MiB)
111+
- `dist/static/js/9861.*.js`:约 2.9 MiB,对应 `mermaid/dist/mermaid.min.js`
112+
- `dist/static/js/6416.*.js`:约 1.2 MiB(未压缩约 4.25 MiB),对应 `echarts/index.js + 571 modules`
113+
- `dist/static/js/vendor-hls.*.js`:约 528 KiB,对应 `hls.js/dist/hls.mjs`
114+
- `dist/d52ec1a71b0b003c7892.mjs`:约 1.0 MiB,对应 `pdfjs-dist/build/pdf.worker.min.mjs`
115+
- `dist/images/732165aa59baa0e9674e.mp4`:约 4.2 MiB,对应 `src/assets-optimized/video/trailer.mp4`
116+
- `dist/images/3b69854a302e6128ab4d.mp3`:约 4.0 MiB,对应 `src/assets-optimized/audio/longnight.mp3`
117+
- `dist/images/2c1a073543dd765ee06c.mp3`:约 3.9 MiB,对应 `src/assets-optimized/audio/yesterday.mp3`
118+
- `dist/images/45067c353c9c3e4ed796.mp3`:约 3.5 MiB,对应 `src/assets-optimized/audio/hearty.mp3`
119+
- `dist/images/2152655c1d61800e86a3.mp3`:约 2.0 MiB,对应 `src/assets-optimized/audio/heart-of-the-sea.mp3`
120+
- `dist/images/f5fb3175e80af3f631cc.png`:约 1.4 MiB,对应 `src/assets/images/spring.png`
121+
- `dist/images/916ddb5adf113a8dd7a3.png`:约 1.1 MiB,对应 `src/assets/images/he.png`
122+
- `dist/images/695c6a7e4d55286b3565.png`:约 1.0 MiB,对应 `src/assets/images/song.png`
123+
- `dist/images/9ce539741014a14d8c0c.png`:约 909 KiB,对应 `src/assets/images/xue.png`
124+
125+
### 主要来源归因
126+
127+
#### 1) 音频资源块过大
128+
129+
- 来源:`src/components/stateless/FixMusicPlayer/data/songs.js`
130+
- 影响:`ReactMusic` 页面对应 chunk 里直接带入 4 首本地 mp3,总体超过 14 MiB。
131+
- 现状:`songs.js` 在模块顶层直接 import 本地音频与封面图,构建时会稳定打进产物。
132+
133+
#### 2) 视频资源块过大
134+
135+
- 来源:`src/pages/video/index.jsx``src/components/stateless/LandingPage/index.jsx`
136+
- 影响:同一份 `trailer.mp4`4.2 MiB,且属于本地静态资源,不经过自适应码率或 CDN 流式分发。
137+
138+
#### 3) 首页同步带入 PDF Worker
139+
140+
- 来源:`src/pages/home/index.jsx` 同步 import `InteractiveBook`
141+
- 影响:额外产出约 1.0 MiB 的 `pdf.worker.min.mjs`,即使用户不打开 PDF 书籍功能,也会随站点发布。
142+
143+
#### 4) ChatGPT 页面块偏重
144+
145+
- 来源:`src/pages/chatgpt/index.jsx`
146+
- 主要组成:
147+
- 页面自身及关联模块约 1.5 MiB
148+
- Mermaid 独立 chunk 约 2.9 MiB
149+
- `react-markdown` / `remark-parse` / `remark-rehype` / `unified` 等 markdown 管线被拉入公共路径
150+
151+
#### 5) ECharts 使用全量入口
152+
153+
- 来源:`src/pages/echarts/index.jsx`
154+
- 现状:当前打入的是 `echarts/index.js + 571 modules`,未做按需引入。
155+
156+
#### 6) 菜单 hover 预加载会放大“懒加载页面”的实际网络成本
157+
158+
- 触发点:`src/pages/layout/proSecNav/index.jsx`
159+
- 现状:菜单项 hover 时会执行 `comp.preload()` 与页面模块预取。
160+
- 影响:即便页面路由本身是懒加载,用户悬停菜单后仍可能提前下载 `ChatGpt``Echarts``ReactMusic``MyVideo` 等重页面资源。
161+
162+
## 具体瘦身建议
163+
164+
### 优先级 P0:先处理媒体资源
165+
166+
-`FixMusicPlayer` 的歌曲清单从“顶层静态 import”改为“元数据 + 点击时再解析 URL / 拉取资源”。如果这些资源只是演示素材,优先改成外链/CDN。
167+
-`trailer.mp4` 改成更低码率版本,至少补一份 `webm` 或更低分辨率资源。若只是展示页背景视频,优先提供 poster,滚动到可视区域或用户点击后再加载。
168+
-`spring.png``he.png``song.png``xue.png` 转成 `webp/avif`,并按展示尺寸重新导出。它们目前在首页、Demo、Tilt、FeatureAny、AutoSlider 等多个位置复用,体积收益会立刻体现。
169+
170+
### 优先级 P1:减少默认路径上的重功能
171+
172+
- 将首页里同步引入的 `InteractiveBook` 改成真正的动态加载,避免默认构建始终产出并暴露 1 MiB 的 PDF worker。
173+
-`ChatGpt` 页里的 Mermaid 能力再拆一层:只有检测到 Mermaid 代码块或用户打开 Mermaid 面板时再加载 Mermaid。当前虽然 Mermaid 已是独立 chunk,但菜单预加载会放大实际下载成本。
174+
- 评估 `src/pages/layout/proSecNav/index.jsx` 的 hover 预加载策略,至少把 `ChatGpt``Echarts``ReactMusic``MyVideo``BigScreen` 这类重页面从自动预取名单里拿掉。
175+
176+
### 优先级 P2:收缩第三方库体积
177+
178+
- `echarts` 改成按需注册方式,不再使用全量入口。目标是只引入当前图表页实际使用的 chart、component、renderer。
179+
- `lodash` 当前进入 `vendor` 的是整包 `lodash/lodash.js`。优先替换为按方法导入,或迁移到 `lodash-es` 并交给 tree-shaking。
180+
- `hls.js` 已经被拆成独立 chunk,方向基本正确。后续只需避免非 HLS 场景触发预加载即可。
181+
182+
## 建议的落地顺序
183+
184+
1. 先处理本地音频与视频资源。
185+
2. 再把首页 `InteractiveBook` 改成动态加载。
186+
3. 再缩减菜单 hover 预加载名单。
187+
4. 最后做 `echarts``lodash` 的代码级瘦身。
188+
189+
## 依赖回退说明:filemanager-webpack-plugin 10.0.0
190+
191+
### 结论
192+
193+
- 当前仓库应保持 `filemanager-webpack-plugin``^9.0.1`
194+
- 不要升级到 `10.0.0`,除非上游重新发布修复版本并验证通过。
195+
196+
### 回退原因
197+
198+
- 本项目的 Webpack 生产配置文件 `webpack/webpack.prod.js`ESM
199+
- `filemanager-webpack-plugin@10.0.0` 的 npm 发布包中实际包含的是 `dist/index.mjs`,但其 `package.json` 却将 `import`/`module` 入口声明为 `dist/index.js`
200+
- 结果是:Webpack CLI 在加载 ESM 配置时会直接报错,无法解析该插件入口。
201+
202+
典型报错如下:
203+
204+
```text
205+
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../node_modules/filemanager-webpack-plugin/dist/index.js'
206+
Did you mean to import "filemanager-webpack-plugin/dist/index.cjs"?
207+
```
208+
209+
### 为什么回退到 9.0.1
210+
211+
- `9.0.1` 的发布包同时包含 `dist/index.js``dist/index.cjs`,其包元数据与实际产物一致。
212+
- 在该版本下,`webpack/webpack.prod.js` 可以继续使用标准 ESM 写法:
213+
214+
```javascript
215+
import FileManagerPlugin from 'filemanager-webpack-plugin'
216+
```
217+
218+
### 升级前检查建议
219+
220+
如果后续需要重新评估升级,请先确认两点:
221+
222+
1. `npm pack filemanager-webpack-plugin@<version>` 解包后,ESM 入口文件是否真实存在。
223+
2. `SKIP_OPTIMIZE_MEDIA=1 npm run build:production` 是否可以无兼容补丁直接通过。
224+

package-lock.json

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
"eslint-plugin-storybook": "^10.2.16",
265265
"eslint-plugin-unicorn": "^63.0.0",
266266
"eslint-webpack-plugin": "^5.0.3",
267-
"filemanager-webpack-plugin": "^10.0.0",
267+
"filemanager-webpack-plugin": "^9.0.1",
268268
"fork-ts-checker-webpack-plugin": "^9.1.0",
269269
"gh-pages": "^6.3.0",
270270
"glob": "^13.0.6",

0 commit comments

Comments
 (0)