一个 Next.js WebGL 小游戏从 Lighthouse 40+ 到 97 的性能优化记录

winterscott999 2026-07-21 17:10 1

最近做了一个基于 Next.js 、React 和 PixiJS 的网页小游戏 Color Tiles。


页面看起来不复杂:一个 WebGL 棋盘、几个控制按钮,加上一些玩法介绍。但第一次跑移动端 Lighthouse 时只有四十多分。最初的报告没有保存下来,目前仓库里能复核的中间结果是 59 分:



  • LCP:11.36 s

  • TBT:625 ms

  • 首屏传输量:2.33 MB


经过几轮优化后,生产构建的移动端 Lighthouse 达到 97 分,桌面端 100 分:



  • LCP:2.29 s ,下降约 80%

  • TBT:135 ms ,下降约 78%

  • 首屏传输量:509 KB ,下降约 78%

  • CLS:保持为 0


这次比较有效的改动主要有这些:



  1. 不再整包引入 pixi.js-legacy,改为从 @pixi/core@pixi/display@pixi/sprite 等模块按需引入,并直接使用 WebGL Renderer 。

  2. 把只能在浏览器运行的游戏模块改成动态加载,同时保留尺寸稳定的 loading 界面,避免布局跳动。

  3. 把教程 GIF 转成 MP4 ,并延迟到用户真正打开教程时再加载。

  4. 图片转为 WebP ,补全响应式 sizes,并通过 Cloudflare Image Resizing 输出适合设备尺寸的版本。

  5. 把图片迁移到独立的 img.colortilesgame.net CDN 子域名,静态资源缓存延长到一年,并使用 immutable。同时用 preconnect 提前完成新域名的连接。

  6. 开启 Next.js 的实验性 inlineCss,把 CSS 放进 HTML ,减少首次渲染中的一次阻塞请求。

  7. 排行榜 API 改为接近视口或游戏结束后再请求,不再与棋盘初始化争抢首屏资源。


过程中也踩了几个坑。例如,一开始 preload 了完整背景图,以为可以改善 LCP ,结果大图反而提前占用网络。后来只 preload 4.8 KB 的占位图,效果更合理。


另一个体会是,不要只盯着 Lighthouse 总分。中间报告的 FCP 已经不到 1 秒,真正的问题是 11 秒的 LCP 、主线程阻塞和过大的资源量。把非关键工作移出首屏,比继续抠 FCP 更有效。


线上版本:


https://colortilesgame.net


更完整的过程、代码片段、数据和取舍写在 Medium:


https://medium.com/@winterscott999/from-the-40s-to-97-how-we-cut-the-initial-load-of-a-next-js-webgl-game-by-nearly-80-d04e803a27ac


欢迎交流 WebGL 游戏、Next.js 或 Lighthouse 优化方面的经验。

最新回复 (2)
  • yinglian 07-21 17:34
    1
    这游戏滑动有点小延迟,其他还好
  • winterscott999 楼主 07-21 17:50
    2
    @yinglian 回头优化一下,应该是时间缩短就可以。
* 帖子来源V2EX
返回