neptay
全部洞察

工程技术

一秒以内的工作室网站:我们交付时遵循的性能预算

我们如何交付在中端手机、4G 网络下一秒内完成首次内容绘制的工作室网站——我们给自己定下的预算、被砍掉的东西,以及对 Core Web Vitals 影响最大的几项架构小决策。

本文目录

有这样一类工作室网站——每次滚动都会触发视差闪烁、字体替换、一段要缓冲三秒的自动播放视频,还有一个悬停时会长出獠牙的光标——在中端手机上要八秒才能加载完,在光纤以外的任何网络上都像是坏了。我们不做这样的网站。我们给自己定的要求简单而严苛:在 Pixel 6a 上、经限速的 4G 网络下,首次内容绘制不超过一秒。

达到这个要求,靠的不是英雄式的优化,而是少数几个会产生复利效应的架构选择,以及一长串我们坚决不做的事。本文介绍我们遵循的预算、背后的决策,以及证明预算已经守住的真实环境测量数据。如果你在做工作室网站、代理公司网站,或任何作品集形态的页面,这是一个几乎可以整体照搬的实战目标。

预算,用数字说话

我们交付的每个工作室网站,都以 Pixel 6a 在 Chrome DevTools 的 Fast 3G 限速下的表现为目标。真实的 4G 网络会更快;我们把 Fast 3G 作为最坏情况下的下限。我们用 Lighthouse 进行测量,并在生产环境中通过 Vercel Analytics 收集真实用户指标。

  • 最大内容绘制(LCP):实验室环境低于 1.2s,真实环境 p75 低于 1.8s。Google 的“良好”阈值是 2.5s。
  • 首次内容绘制(FCP):实验室环境低于 1.0s。
  • 累积布局偏移(CLS):低于 0.05。Google 的“良好”阈值是 0.1,我们要求自己做到它的一半。
  • 与下一次绘制的交互(INP):低于 100ms。Google 的“良好”阈值是 200ms。
  • 首次加载的总传输体积:压缩后低于 150KB,包含 HTML、CSS、字体、JS 和首屏大图。
  • 首次加载的 JavaScript 包:压缩后低于 80KB。

只要页面有任何一项未达标,我们就把它当作 P1 级缺陷处理。不是“以后再说”,而是上线前必须修复的 P1。

为什么这么严格?

原因有二。第一,Core Web Vitals 是 Google 的排名因素。不是用来打破平局的附加项——而是实打实的排名因素。达到阈值的网站有资格获得页面体验加成;达不到的,则会在边际上受到惩罚。对一家在细分关键词集群中竞争的工作室来说,这点边际至关重要。

第二,感知性能本身就是一种品牌信号。瞬间加载的网站,让人觉得专业可靠;因为等待某个追踪像素而卡住的网站,则不然。对于一家主打“我们交付经过深思熟虑的现代作品”的工作室来说,网站必须在第一次接触时就证明这一点。网站本身,就是提案。

决策 1:全部静态渲染

最重要的性能决策是渲染策略。我们使用 Next.js 的 App Router,工作室网站上的每个页面都在构建时静态渲染。没有运行时数据库查询;除了负责分发 HTML 的边缘函数,没有任何逐请求的服务器工作。整个网站就是 CDN 上的一组文件。

具体能换来什么:边缘的 TTFB 取决于你的 CDN——在全球任何地方,通常都是 30–80ms。HTML 的第一个字节到达时,换作服务端渲染的方案,浏览器可能连 TLS 握手都还没完成。下游的一切——绘制、可交互、下一个页面——都会随之提前。

代价是,内容变更需要重新部署。对于每月更新一次的工作室网站,部署根本不算事——在 Vercel 上只需 90 秒。对于每小时更新的媒体网站,账就要另算了,ISR(增量静态再生成)才是合适的工具。但工作室网站不会每小时更新。

决策 2:一种网页字体,两种字重

自定义字体是首次绘制中最大的一项可控开销。单一字重的网页字体子集,压缩后通常为 25–40KB。一个加载两个字体家族、各三种字重的网站,在第一个字节的内容绘制出来之前,就要传输 150KB 的字体。我们只用一个字体家族、两种字重,通过 next/font 以自托管、带哈希的方式分发——没有 Google Fonts 的第三方请求,也不需要对字体 CDN 做 DNS 查询。

我们也接受随之而来的结果:没有斜体,没有细体,没有特粗体。每一种排版上的区分,都必须通过字号、颜色、字距,或我们仅有的两种字重之间的对比来实现。这是一种物有所值的创作约束。需要八种字重的网站,往往是在用字体的花样掩盖层级的混乱;只用两种字重的网站,必须从结构上把层级做对。

决策 3:首屏大图预算——以及如何花好它

在工作室网站上,LCP 几乎总是首屏大图。所以 LCP 预算就是首屏大图的预算。我们给首屏大图设定了严格上限:桌面断点下压缩后 80KB,移动端 40KB。任何更大的图片,都是需要在选图或图片处理上解决的创作问题,而不是超支的借口。

帮助我们守住预算的四个做法:

  1. 在支持的浏览器中使用 AVIF,并以 WebP 作为回退。在同等画质下,AVIF 通常比 WebP 小 30–40%。
  2. 通过 next/image 组件提供响应式尺寸。手机永远不会下载桌面端的首屏大图;桌面端也不会下载 2 倍视网膜版本,除非屏幕真的是视网膜屏。
  3. 为每张图片设置明确的宽度和高度。这正是防止布局偏移的关键——浏览器会在图片到达之前预留出正确的像素空间。
  4. 预加载首屏大图。在 head 中加入 <link rel="preload" as="image" href="…"/>。只需一行代码,就能让 LCP 缩短 200–400ms,因为浏览器会在解析页面其余部分之前就开始请求这张图片。

决策 4:JavaScript 是最后的手段

每一千字节的 JavaScript,都必须在页面可交互之前完成下载、解析,并在主线程上执行。我们把 JS 预算视为稀缺资源,并坚守两条规则:

  • 默认使用服务器组件。只有真正需要交互的组件,才标记为 'use client'。React Server Components 的默认设置,对内容为主的网站来说就是正确的默认。
  • 首次加载时不引入任何第三方脚本。不用动辄附带 80KB 供应商代码的分析工具,不用标签管理器。分析脚本在页面可交互之后才延迟加载——我们使用 Vercel Analytics,它只有约 1KB。

我们为工作室网站设定的预算,是首次加载的压缩 JS 低于 80KB——其中大部分是 React 本身。交互层(导航菜单、语言切换、联系表单)只有几 KB。

决策 5:不会带来布局偏移问题的 CSS 架构

累积布局偏移是最容易在不经意间失分、也最容易有意修好的一项 Core Web Vital。让 CLS 接近于零的四个习惯:

  1. 为所有晚到的内容预留空间。图片、字体、iframe、广告——全部放进设有明确尺寸的宽高比容器中。
  2. 避免依赖字体加载完成的 CSS。在字体替换期间使用系统字体作为回退,并设置 font-display: swap。选择与网页字体度量相近的回退字体,让替换过程不留痕迹。
  3. 不要在加载完成后往首屏插入内容。首次绘制之后才出现的横幅、Cookie 提示和公告栏,就是一场随时会发生的布局偏移。如果确实需要,就把它们写进初始 HTML,再用动画呈现出来。
  4. 在慢速网络下测试。在光纤上看不出的 CLS 问题,会在 3G 上暴露出来,因为晚到的资源会到得最晚。

决策 6:动画预算

克制地使用动效,本身就是一种性能优化。每一个在主线程上运行的动画,都有让 INP 退化的风险——点击时一个卡顿 250ms 的动画,就足以把整个网站挤出 INP 的“良好”区间。我们的规则:

  • 只对 transform 和 opacity 做动画。两者都由 GPU 合成,不会触发布局计算。
  • 入场动画用 CSS 实现,而不是 JavaScript。我们用 IntersectionObserver 添加一个 className,真正的动画则是一个 transition。
  • 不用滚动联动动画。它们听起来很优雅,但在中端设备上会带来糟糕的滚动性能。
  • 首屏不放自动播放的视频。如果确实需要视频,就把它延迟加载到首屏以下,或放在一次交互之后。

决策 7:无障碍与性能的重叠

大多数无障碍改进,同时也是性能改进。语义化 HTML 比层层嵌套的 div 更小。原生焦点环比自定义的 JS 焦点管理渲染得更快。页首的跳转链接,免去了那些需要附带 JavaScript 的键盘陷阱修复。我们从一开始就以无障碍为先进行设计和开发;性能随之而来,不费分毫。

性能与无障碍之间唯一存在张力的地方是动画。有些用户需要动效,有些用户则会因此头晕不适。我们尊重 prefers-reduced-motion,并为每个入场动画提供回退方案——淡入,而不是位移。

在生产环境中测量

Lighthouse 的实验室指标必要,但不充分。黄金标准是真实用户监控(RUM)——真实访客在真实设备上的实际体验。我们使用 Vercel Analytics 监测 Web Vitals,因为它随平台免费提供,并按路由、设备和地域细分报告真实环境指标。

我们每周关注的内容:

  • 每条路由的 p75 LCP。只要有任何路由的 p75 超过 1.8s,我们就会排查。
  • INP 退化。INP 是最隐蔽的指标——随着 JavaScript 增加,它可能在不知不觉中变差。
  • 按路由统计的 CLS。CLS 退化通常可以追溯到某一个加载较晚的元素。
  • 按路由统计的首次加载 JS,在 CI 中通过打包分析工具追踪。超出预算的构建,我们会直接判定失败。

我们不做的事

同样重要的是,那些虽然是行业标配、我们却刻意舍弃的东西:

  • 小网站不用 SPA 式的客户端路由。在 4G 网络下,完整获取文档比加载打包增量更快。我们让浏览器自己完成导航。
  • 不用 Service Worker。对一个不到 10 个页面的网站来说,这份复杂度不值得。
  • 不用会注入 30KB SDK 的图片托管服务。我们从网站自己的域名提供图片,并在构建时完成优化。
  • 不用“智能”懒加载库。原生的 loading="lazy" 属性就能胜任,而且是 0KB。
  • 不在悬停时预取所有链接。Next.js 在生产环境中默认会进行预取;我们保持开启,让框架自行决定。

如果你正在规划一个网站,想为现有网站做一次性能审计,或者希望从一开始就按这套预算来构建,请联系 hello@neptay.com。

Neptay Media & Technology Services

聊聊吧

正在筹划类似的项目?

这些文章中的方法,正是我们在客户项目中使用的方法——涵盖软件开发、AI 自动化、内容制作、社交媒体与直播制作。告诉我们您的想法,我们将在 24 小时内回复。