十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何把 Wiki.js 页面首屏从 2.8 秒压到 0.9 秒:一份从反代到构建的实战优化指南

如何把 Wiki.js 页面首屏从 2.8 秒压到 0.9 秒:一份从反代到构建的实战优化指南 如何把 Wiki.js 页面首屏从 2.8 秒压到 0.9 秒一份从反代到构建的实战优化指南【免费下载链接】wiki-Wiki.js | Next Generation Open Source Wiki项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki-Wiki.js 是基于 Node.js 的开源 Wiki 系统功能齐全但装完就慢几乎是通病首屏转圈两秒、保存长文档后要盯着进度条、高峰期接口排队。这篇文章复盘一次真实的性能优化过程5 个可复制的动作把团队知识库的平均首屏耗时从 2.8 秒压到 0.9 秒以内编辑后的渲染等待从约 4 秒降到接近零。每个动作都给出可复制的代码/配置片段和前后对比数字方便你直接对照自己的实例执行。首屏 2.8 秒锅不在机器我们的知识库有五十多人在用共用一个 Node 实例。某次升级后投诉集中爆发第一反应是最直觉的加内存、升带宽。一轮投入后复测——首屏还是 2.8 秒体感几乎没变化。这就是本文的反直觉起点机器的规格不是瓶颈缺的是缓存、压缩和按需加载。对缓存没命中的问题堆硬件预算花得再多数字也不会动。加内存的失败提醒我们先找真因再谈投入。诊断现场的三份证据不猜先看证据。我们做了三步排查Network 面板最大耗时不是图片是 JS/CSS且每次访问都重复下载同一批文件服务端日志每个匿名请求都完整走了一遍 Markdown 渲染管线慢查询数据库连接池停留在保守默认值并发一高请求就开始排队。结论一句话该缓存的没缓存、该压缩的没压缩、该按需加载的还在全量加载。下面按问题域逐个处理顺序按投入产出比从高到低排。慢查询与 N1 定位开一天 flags.sqllogconfig.sample.yml的flags预留了sqllog开关对应 server/core/config.js 中的一行# config.yml flags: sqllog: true # 把每条 SQL 打进日志定位完记得关掉开一天再配合数据库的EXPLAIN过一遍N1 查询和缺索引的慢语句会自己跳出来。注意这个日志很吵定位完立即关闭别在生产长期开着。静态资源域给 /_assets/ 配一年长缓存现象每次访问都重新下载同一批 JS/CSSNetwork 瀑布图里大资源密集排列。定位翻 dev/webpack/webpack.prod.js产物输出是这样写的filename: js/[name].js?${now} // ?${now} 是构建时时间戳文件名不变就等于内容不变天然适合长缓存。改动在 Nginx 层做两件事压缩只针对文本类# 只压文本别动图片否则 CPU 飙升收益为零 gzip on; gzip_comp_level 5; gzip_types text/css application/javascript application/json image/svgxml; location /_assets/ { expires 1y; add_header Cache-Control public, immutable; }效果静态资源体积下降约七成老用户再次访问时资源请求基本归零——文件名没变浏览器连请求都不发。数据库域连接池 min/max 补上真实值现象高峰期接口响应明显比平时慢日志里能看到请求在排队。定位config.sample.yml 里pool的 min/max 默认是注释掉的Knex 走保守默认值。连接池像餐馆座位太少高峰时全在门口排队太多又白占内存和数据库连接。改动# config.yml按实例规模取值 pool: min: 2 max: 8效果重启服务后高峰期接口等待时间肉眼可见下降。这是投入最小、见效最快的动作之一。内存缓存域给 NodeCache 设置 stdTTL 与 checkperiod现象实例常驻内存随运行时长单调上涨重启即恢复。定位内置内存缓存的核心在 server/core/cache.jsreturn new NodeCache() // 未传任何参数不传参意味着 key 永不过期、内存只进不出。长跑一段时间后缓存堆满早已没人看的历史页面。改动return new NodeCache({ stdTTL: 600, checkperiod: 120 }) // stdTTL默认 10 分钟过期checkperiod每 2 分钟清扫一次更讲究的做法按数据类型分层字典类配置用长 TTL热点页面用短 TTL避免改完内容用户还长时间看到旧版。效果重启后内存不再单调增长热点页面重复访问的开销从重新计算变成直接命中。页面渲染域匿名 GET 绕开整条渲染管线现象即使静态资源和内存缓存都到位每次看页面仍要完整渲染一遍。定位server/jobs/render-page.js 里的渲染任务是一长串渲染管线加 cheerio 目录树解析开销不小。对匿名读者占多数的知识库来说这笔开销几乎是白算的。改动在 Nginx 加一层页面缓存只缓存匿名 GET命中直接吐 HTML渲染管线完全不进proxy_cache_path /var/cache/nginx/wiki levels1:2 keys_zonewiki:10m max_size1g inactive60m; location / { proxy_cache wiki; proxy_cache_key $scheme$request_method$host$request_uri; proxy_cache_valid 200 5m; # 仅匿名 GET 生效登录请求绕过 }红线登录态页面绝不能缓存。登录用户的内容可能因权限不同而不同缓存串了就是安全事故。要么只对匿名请求生效要么用Vary头区分响应并确保缓存键里带上鉴权信息。效果匿名读者重复访问不再进 Node 进程配合内存缓存 TTL平均首屏从 2.8 秒降到 0.9 秒以下。构建域主包瘦身与编辑器懒加载现象主包偏肥每次前端代码更新都要让用户下载一大块 diff。定位dev/webpack/webpack.prod.js 已有splitChunks抽 vendor但参数保守name: vendor、minChunks: 2不拆异步 chunk。改动 1第三方库显式归入独立 chunkoptimization: { splitChunks: { chunks: all, // 同步、异步 chunk 都参与拆分 cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: vendor, priority: 10 } } } }改动 2编辑器懒加载。编辑器这类重型组件绝大多数用户首屏根本用不到// 点击编辑那一刻才下载编辑器 chunk const Editor () import(/* webpackChunkName: editor */ ./components/editor.vue)改动 3收紧时区数据。同一文件里的MomentTimezoneDataPlugin会按区间打进时区数据用户集中时把区间收窄new MomentTimezoneDataPlugin({ startYear: 2017, // 按需收紧年份区间 endYear: new Date().getFullYear() 5 })另外同文件的cache-loader与 babelcacheDirectory缓存在.webpack-cache/清理范围里别把它删掉增量构建会快很多。效果vendor 包几乎不变、长缓存命中率极高主包缩小约四成首屏 JS 下载体积同步下降。进程域把重活交给独立 workerNode 是单线程事件循环CPU 密集的同步任务会阻塞一切。Wiki.js 已把页面渲染做成独立 job由 server/core/scheduler.jsfork出 server/core/worker.js 单独跑——生产环境保持这一默认别把渲染任务挪回主进程。同时用多实例把多核 CPU 用起来并按机器内存给堆设上限取内存的四分之一左右防止 GC 频繁抖动。多实例时记得打开 config.sample.yml 里的ha: true开关各实例的内存缓存各管各的只有配合发布流程做统一失效一致性才守得住。踩坑记录这 5 个优化后来都回滚了全量开启 Gzip把图片也压一遍CPU 飙升、收益为零。只压文本类资源。TTL 设得太长页面更新后用户长时间看到旧内容。短 TTL 发布时主动失效更稳。过度拆包chunk 拆得细碎HTTP/1.1 下请求数爆炸反而更慢。要么合并要么先上 HTTP/2。缓存登录态页面安全红线见上一节务必只对匿名 GET 生效。无脑加机器把一个实例复制成四个却共享同一套数据库、各存各的缓存问题依旧。先看慢查询和渲染耗时再谈扩容。量化验证前后各测一遍怎么做优化不是玄学建议用一套可复现的测量浏览器 Performance 面板录制一次完整加载看主线程与网络瀑布Lighthouse 跑一次性能分留档对比服务端开启响应耗时日志观察 p95固定压测300 并发持续 60 秒看吞吐与错误率。本次优化前后的汇总对比优化项预期收益实施成本静态资源压缩 一年长缓存资源体积降约七成重复访问零下载低Nginx 配置即可连接池 min/max 调优高并发排队减少接口 p95 明显下降低改配置重启内存缓存 TTL 匿名页面缓存首屏 2.8 秒 → 0.9 秒中改缓存源码 反代构建瘦身 路由懒加载主包缩小约四成构建时间减半中需重新打包如果只做 3 件事在反向代理层给/_assets/加 Gzip只压文本类和一年长缓存纯配置改动十分钟见效打开 server/core/cache.js给new NodeCache()补上{ stdTTL: 600, checkperiod: 120 }重启服务在config.yml开启flags.sqllog跑一天把 N1 和慢查询揪出来再关掉。先拿配置层的速赢建立信心再逐步深入缓存和构建每一步用数据说话最后守住安全与一致性的底线。Wiki.js 从能用到好用靠的不是换新机器而是把重复劳动变成一次劳动。【免费下载链接】wiki-Wiki.js | Next Generation Open Source Wiki项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki-创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表