Wiki.js 提速实战:4 个真实卡顿场景,把首屏从 3 秒压进 1.5 秒
【免费下载链接】wiki-Wiki.js | Next Generation Open Source Wiki项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki-
一次真实排障是这样的:某团队反馈 Wiki.js 页面"转圈慢",我们用 Lighthouse 一跑,TTFB 1.2s、JS 传输 1.8MB、编辑保存要 2s——三个瓶颈分属网络传输、静态资源和数据库三条链路。定位清楚后,没有动一行业务代码,首屏就落到了 1.5s 以内。
这篇文章按你实际会遇到的卡顿场景来组织:先讲这个症状对应的瓶颈在哪,再给解法。每个解法都标注了预期收益和落地成本,你可以按优先级挑选。全文涉及的核心路径都是仓库内真实存在的文件,方便直接定位。
场景一:首屏白屏 3 秒,卡在"传输"上
收益:减少 HTTP 往返与传输体积,首屏通常可快 30%~50%。
白屏久的第一嫌疑往往不是服务器慢,而是"路上堵":资源没压缩、没缓存、重复请求。按下面三步走:
1. 先确认 Gzip 是否生效。在 Nginx 等反向代理里打开对文本类资源的压缩,收益立竿见影(一段典型配置就是gzip on+ 把text/css、application/javascript、image/svg+xml写进gzip_types,此处不贴全文,参数名对得上即可)。验证方式很简单:浏览器 DevTools 里 Network 面板看传输大小,压缩后 JS 体积一般降到原来的 1/3 左右。
2. 确认缓存失效策略。Wiki.js 的构建脚本dev/webpack/webpack.prod.js已经把资源文件名带上了构建时间戳(filename: js/[name].js?${now}),这意味着每次重新构建后浏览器一定会拉新资源——你只需要保证 CDN 或 Nginx 对/_assets/目录设置了足够长的Cache-Control,就能让"版本更新"和"日常命中缓存"两不误。
3. 关注产物体积。同一份 webpack 配置里,MinChunkSizePlugin把低于 50KB 的碎片 chunk 合并掉,图片小于url-loader的limit: 8192时直接内联成 Base64。如果你要自己二次调优,只动两处:optimization.splitChunks(当前是name: 'vendor'+minChunks: 2)和 url-loader 的limit。例如:
optimization: { splitChunks: { name: 'vendor', minChunks: 2, maxInitialRequests: 3 }, runtimeChunk: 'single' }改完重新构建,对比assets/js/下的 chunk 数量和体积即可验证。
场景二:匿名读者重复刷同一页,服务器 CPU 白忙
收益:热点页面请求不再穿透到数据库,CPU 占用可明显下降(压测常见 20%~40%)。
Wiki.js 的缓存分两层:
- 内存层:
server/core/cache.js基于 NodeCache,进程内读写,速度最快; - 磁盘层:
config.sample.yml中的dataPath(默认./data)下会生成cache/目录,server/core/system.js启动时清空、运行中由模型层按需读写,主要给上传资源和渲染产物兜底。
三个可落地的动作:
| 动作 | 怎么做 | 难度 |
|---|---|---|
| 给内存缓存加默认 TTL | NodeCache 初始化时传stdTTL(如 300 秒),防止脏数据常驻 | 低 |
| 集群部署换 Redis | 多实例(K8s 多 Pod、HA 模式)下内存缓存各存各的,可替换为共享的 Redis 层 | 中 |
| 定期清理磁盘缓存 | 对${dataPath}/cache做定时清理或随发布流程清理 | 低 |
HA 场景值得多说一句:config.sample.yml里的ha: true是给"多实例共享同一 PostgreSQL"的高可用部署准备的,此时本地内存缓存的命中率会因请求被负载均衡打散而下降,这一步换 Redis 的收益才真正显形。
场景三:编辑保存转圈,瓶颈在数据库
收益:消除慢查询与连接等待,保存/加载延迟通常降一半。
"转圈"这类写操作卡顿,十有八九发生在 SQL 层。排查分两步:
1. 打开 SQL 日志抓现行。在配置中启用flags.sqllog: true(实现见server/core/config.js的applyFlags(),它把开关透传给 knex 的debug)。日志里按时间排序,超过 500ms 的语句基本就是元凶——常见的是缺索引的大表扫描。
2. 调连接池。config.sample.yml的pool段(注释态)对应 tarn.js 的池参数:
pool: min: 2 max: 10原则:max不要盲目调大。它是"并发连接上限",超过 PostgreSQL 默认max_connections容量时反而会引发连接排队,把延迟推高。先观察日志里是否有"获取连接等待",再按 QPS 逐步上调。
另外,server/models/下每个模型对应一类数据访问,排障时按模型名 grep SQL 日志能快速锁定是哪条业务路径慢,这是读这份代码成本最低的方式。
场景四:高峰期偶发变慢,进程层面没留余量
收益:单实例扛住更多并发,避免 GC 抖动带来的偶发卡顿。
三个部署层的调整,都不需要改代码:
- 给 V8 留够堆:Node 启动参数加
--max-old-space-size=2048(按容器内存配额定),减少堆满触发的 Full GC 停顿; - 多核利用:用 PM2 的 cluster 模式起多实例(
pm2 start加-i max)——但注意这与 HA 场景二挂钩,多进程后建议同步评估 Redis 缓存与ha: true的设置,否则各实例缓存互不共享; - 压测验证:用
ab -n 100 -c 10 <你的页面 URL>跑一轮基准,记录 p95 延迟,再与调优后对比。
度量与固化:让提速不是一次性的
- 建一个基线:调优前用 Lighthouse +
ab各跑一次,把首屏时间、p95 延迟、CPU 占用记成三个数,之后每次改动后复测; - 看应用性能指标:
server/modules/analytics/下有 elasticapm、newrelic 等模块,启用任意一个即可拿到服务端 trace,比纯猜快得多; - 固化流程:把"重建前端资源 → 清
dataPath/cache→ 压测对比"写成发布前的 checklist。
避坑三条
- 先测量再动手。没有基线数字的优化都是玄学——Gzip 是否生效、SQL 是否真的慢,都先验证再改,避免"改了一堆参数,快不快不知道"。
- 改 webpack 配置后必须完整重建并对比产物。
dev/webpack/webpack.prod.js里时间戳缓存失效、excludeChunks按入口拆分视图模板(见dev/templates/master.pug的生成逻辑),改动 chunk 策略后确认server/views/下各模板仍能正确引用对应 JS。 - 动
config.sample.yml对应配置前先备份数据库。连接池、HA 这类改动影响面是全局的,出问题时恢复成本很高。
更多安装与运行细节,可参考仓库内的 README.md。
【免费下载链接】wiki-Wiki.js | Next Generation Open Source Wiki项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki-
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考