Wiki.js 性能优化指南:首屏 2.8 秒到 0.9 秒的会诊报告
【免费下载链接】wiki-Wiki.js | A modern and powerful wiki app built on Node.js项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki-
Wiki.js 是一款基于 Node.js 的现代知识库应用,功能强,但部署后首屏慢很常见。这轮 Wiki.js 性能优化走了一条会诊路线:先看症状,再依次排查前端、数据库、缓存、构建、进程五个部位,平均首屏从 2.8 秒降到 0.9 秒,保存后的等待基本消失。
卡在哪
🔴Network 面板:最重的是 JS/CSS,且每次访问都重新下载。判断:静态资源没有长缓存策略,浏览器在反复拉取没变过的版本。
🟠服务端日志:每个匿名请求都完整走一遍 Markdown 渲染管线,渲染耗时稳定偏高。判断:大量 HTML 在重复现算,属于重复劳动。
🟡SQL 日志:高峰期同类慢语句排队,连接等待时间拉长。判断:数据库连接池用了保守默认值,并发一来就开始排队。
排查路线
静态资源开一年缓存
前端资源文件名自带时间戳,名字不变即内容不变,天然适合长缓存。反向代理层只对文本类资源开 Gzip,并给/_assets/路径设置一年缓存:
gzip on; gzip_types text/css application/javascript application/json image/svg+xml; location /_assets/ { expires 1y; add_header Cache-Control "public, immutable"; }效果:资源传输体积降约七成,老用户再次访问时资源请求基本归零。
连接池 min/max 怎么定
config.sample.yml 中pool项默认被注释,Knex 会退回保守默认值,并发一来请求就排队。min/max 按实例数与内存定,取中间值即可:
pool: min: 2 max: 8重启后高峰期接口等待明显下降。顺手在 config.yml 的flags下开启sqllog: true跑一天,N+1 查询和缺索引的慢语句会自己冒出来,定位完记得关闭,这个日志很吵。
给内存缓存设过期时间
server/core/cache.js 里的new NodeCache()没传任何参数,key 永不过期,内存只进不出。补上默认 TTL 和定期清理:
return new NodeCache({ stdTTL: 600, checkperiod: 120 })讲究一点再分层:配置类字典用长 TTL,热点页面用短 TTL,避免用户长时间看到旧内容。另外在反向代理层给匿名 GET 加页面缓存,只缓存 200 响应五分钟,命中后直接返回 HTML,渲染管线完全不进。务必只缓存匿名请求,登录态页面绝不能进缓存。
主包拆分与编辑器懒加载
默认 splitChunks 参数偏保守,编辑器这类重型组件被打进首屏包,时区数据还是全量。用chunks: 'all'把第三方依赖拆成独立 vendor,编辑器改为按需加载:
const Editor = () => import(/* webpackChunkName: "editor" */ './components/editor.vue')vendor 包几乎不变,长缓存命中率极高。同时收紧 webpack.prod.js 里 MomentTimezoneDataPlugin 的 startYear/endYear 区间裁掉用不到的时区表;保留.webpack-cache/目录,增量构建会快很多。
渲染交给 worker,堆内存设上限
页面渲染是 CPU 重活,和 Web 请求挤在同一个事件循环里会互相拖累。生产环境把这类 job 交给独立 worker 进程;用多实例吃满多核,并把堆内存上限设为物理内存的四分之一左右,减少 GC 抖动。
处方验证
| 指标 | 优化前 | 优化后 | 对应动作 |
|---|---|---|---|
| 平均首屏 | 2.8 秒 | 0.9 秒 | 静态长缓存 + 匿名页面缓存 |
| 资源传输体积 | 基准 | 降约七成 | Gzip + 一年缓存 |
| 主包体积 | 基准 | 降约四成 | 主包拆分 + 路由懒加载 |
| 高并发接口 p95 | 排队明显 | 大幅下降 | 连接池 min/max 调整 |
| 构建耗时 | 基准 | 约减半 | 构建缓存 + 产物裁剪 |
验证手段用四个:浏览器 Performance 面板录一次完整加载,看瀑布图与主线程;Lighthouse 跑一次性能分;服务端开响应耗时日志观察 p95;最后用压测打 300 并发持续 60 秒,观察吞吐与错误率。
长期保养
- Gzip 不要压图片:只压缩文本类资源,全量压缩只会让 CPU 飙升、收益为零。
- TTL 别拉太长:短 TTL 加内容发布时主动失效,比一味拉长缓存更稳。
- 登录态页面不进缓存:内容随权限变化,缓存串了就是安全事故,缓存键必须只覆盖匿名请求。
- 多实例注意缓存一致性:各实例的内存缓存各管各的,要配合发布流程做统一失效。
持续监控建议:保留响应耗时日志,定期复跑一次压测并对比 p95 走势;每次发新版后,对照上表把指标重新过一遍。
今晚就能做的最小动作:在反向代理给/_assets/加 Gzip 和一年缓存,十分钟完成。再把 server/core/cache.js 补上stdTTL与checkperiod,重启服务。报告已开好,后面只需要按改一处、看一组数字的节奏执行。
【免费下载链接】wiki-Wiki.js | A modern and powerful wiki app built on Node.js项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki-
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考