<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>树的小站 Blog</title>
        <link>https://shu.moe/posts</link>
        <description>树的小站 Blog</description>
        <lastBuildDate>Tue, 26 May 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-Hans</language>
        <item>
            <title><![CDATA[如何让网站的速度更快]]></title>
            <link>https://shu.moe/posts/web-faster</link>
            <guid>https://shu.moe/posts/web-faster</guid>
            <pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[做好每一个工作环节，更快，更稳定。]]></description>
            <content:encoded><![CDATA[<p>做好每一个工作环节，更快，更稳定。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="缩小文件加载体积">缩小文件加载体积<a href="https://shu.moe/posts/web-faster#%E7%BC%A9%E5%B0%8F%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD%E4%BD%93%E7%A7%AF" class="hash-link" aria-label="缩小文件加载体积的直接链接" title="缩小文件加载体积的直接链接" translate="no">​</a></h2>
<ol>
<li class="">开启服务器 gzip 压缩，可以缩小文件传输体积</li>
<li class="">通过代码转译工具，可以缩小代码产出文件体积<!-- -->
<ol>
<li class="">js 转译可以使用 <a href="https://github.com/terser/terser" target="_blank" rel="noopener noreferrer" class="">terser</a></li>
<li class="">css 转译可以使用 <a href="https://lightningcss.dev/" target="_blank" rel="noopener noreferrer" class="">lightningcss</a></li>
<li class="">html 压缩可以使用 <a href="https://github.com/j9t/html-minifier-next" target="_blank" rel="noopener noreferrer" class="">html-minifier-next</a></li>
</ol>
</li>
<li class="">文字、图片、视频，也都有相关的文件大小降低方案<!-- -->
<ol>
<li class="">文字加载可以使用 <a href="https://fontsource.org/docs/getting-started/introduction" target="_blank" rel="noopener noreferrer" class="">fontsource</a></li>
<li class="">图片压缩可以使用 <a href="https://tinypng.com/" target="_blank" rel="noopener noreferrer" class="">https://tinypng.com/</a></li>
<li class="">视频压缩可以使用 <a href="https://www.ffmpeg.org/" target="_blank" rel="noopener noreferrer" class="">ffmpeg</a> 降低码率</li>
</ol>
</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="降低初始运行时间">降低初始运行时间<a href="https://shu.moe/posts/web-faster#%E9%99%8D%E4%BD%8E%E5%88%9D%E5%A7%8B%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4" class="hash-link" aria-label="降低初始运行时间的直接链接" title="降低初始运行时间的直接链接" translate="no">​</a></h2>
<p>从打开网站，到用户看到可感知的内容，这段时间越快，就代表网站的打开速度越快。<br>
<!-- -->如果你是一个偏图文的网站，内容可以放进 html 中，html 加载完成，用户就是可以阅读的，这样的加载感知是最快的。很多电商网站就是这样做的。<br>
<!-- -->如果你需要在用户端获取并且展示额外数据，额外数据还很大的时候，那就需要告知用户，我需要你等。这个在游戏、重前端的应用中会比较常见。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="降低性能开支">降低性能开支<a href="https://shu.moe/posts/web-faster#%E9%99%8D%E4%BD%8E%E6%80%A7%E8%83%BD%E5%BC%80%E6%94%AF" class="hash-link" aria-label="降低性能开支的直接链接" title="降低性能开支的直接链接" translate="no">​</a></h2>
<p>页面内容的渲染，是需要性能支持的。<br>
<!-- -->在 html 页面画 1000 个基础 div 元素，可能感知不到等待时间，但是如果画 2000 个或者更多，就可以明显感知到页面渲染的等待时间了。<br>
<!-- -->渲染内容过多是最常见的性能瓶颈点。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="虚拟滚动">虚拟滚动<a href="https://shu.moe/posts/web-faster#%E8%99%9A%E6%8B%9F%E6%BB%9A%E5%8A%A8" class="hash-link" aria-label="虚拟滚动的直接链接" title="虚拟滚动的直接链接" translate="no">​</a></h3>
<p>这类问题的第一个常见场景是表格。大量表格内容的快速渲染问题，有一个通用的解法，叫做虚拟滚动。<br>
<!-- -->虽然单个表格需要呈现的内容非常多，会导致呈现等待时间很长，但是屏幕能够展示的内容是有限的。我可以选择计算屏幕当前需要展示哪些内容，只渲染这一部分内容，那就可以极大的降低呈现时间了。<br>
<!-- -->这个做法通常可以让表格内容立即呈现，可接受的缺点是，在表格滚动过程中，性能开销会有所增加。<br>
<!-- -->前端最常见的工具库是 react，在 react 中解决这个问题可以使用 <a href="https://github.com/bvaughn/react-virtualized" target="_blank" rel="noopener noreferrer" class="">react-virtualized</a>。<br>
<!-- -->vscode 可以秒开三百万行的空白文件，他的编辑器也有用到这个方法。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="图表">图表<a href="https://shu.moe/posts/web-faster#%E5%9B%BE%E8%A1%A8" class="hash-link" aria-label="图表的直接链接" title="图表的直接链接" translate="no">​</a></h3>
<p>另一个常见场景是图表。图表的内容可能会非常细密，还可能伴随更新需求。通常会使用 canvas 来解决。<br>
<!-- -->canvas 的特点是，输出一张位图，渲染速度很快，比 html 快很多，这在图表需求上是常见的解决办法。<br>
<!-- -->最常见的图表库是 <a href="https://github.com/apache/echarts" target="_blank" rel="noopener noreferrer" class="">echarts</a>，优势是功能稳定，需求支持丰富，使用简单，缺点是体积比较大。<br>
<!-- -->新兴的图表库，比如 <a href="https://github.com/antvis" target="_blank" rel="noopener noreferrer" class="">antv</a>、 <a href="https://github.com/ChartsOrg/Charts" target="_blank" rel="noopener noreferrer" class="">charts</a> 看起来也不错
还有一个老牌图表库是 <a href="https://github.com/d3/d3" target="_blank" rel="noopener noreferrer" class="">d3.js</a>，功能强大，数据处理和交互性都非常强，但是上手会比较难。直接用来处理需求的话，对接手的人要求比较高。一些新出的图表库是基于这个来开发的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="从网络的方面优化加载">从网络的方面优化加载<a href="https://shu.moe/posts/web-faster#%E4%BB%8E%E7%BD%91%E7%BB%9C%E7%9A%84%E6%96%B9%E9%9D%A2%E4%BC%98%E5%8C%96%E5%8A%A0%E8%BD%BD" class="hash-link" aria-label="从网络的方面优化加载的直接链接" title="从网络的方面优化加载的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="http-103-响应">HTTP 103 响应<a href="https://shu.moe/posts/web-faster#http-103-%E5%93%8D%E5%BA%94" class="hash-link" aria-label="HTTP 103 响应的直接链接" title="HTTP 103 响应的直接链接" translate="no">​</a></h3>
<p>网络请求遵循请求 -&gt; 响应的时序逻辑，遵循 html -&gt; css、js -&gt; 字体、图片 的代码执行流程。<br>
<!-- -->那可以加快这个流程吗？有方法的，HTTP 的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Reference/Status/103" target="_blank" rel="noopener noreferrer" class="">103 Early Hints</a>，可以在 HTML 的响应节点，提前告知需要获取哪些资源。本来有多个串联流程，现在优化成了两个串联流程，并且第二个流程的开始时间还提前了一些，自然是会快一点的。<br>
<!-- -->但可惜 safari 不支持 preload，只支持 preconnect。<br>
<!-- -->曾经还有一个类似做法， http2 service push 可以从服务器推资源，也能起到类似请求提前的效果。但是没办法应用客户端缓存，会造成带宽浪费，所以一般不会使用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cdn-优化">CDN 优化<a href="https://shu.moe/posts/web-faster#cdn-%E4%BC%98%E5%8C%96" class="hash-link" aria-label="CDN 优化的直接链接" title="CDN 优化的直接链接" translate="no">​</a></h3>
<p>资源可以分成多个部分，可以按照内容是否发生了变更，来更新 CDN。<br>
<!-- -->完善的前端工程，通常由开源库和业务代码组成，两者的更新频率并不一样。如果能分开放置 CDN，就可以在业务代码更新的时候，开源库仍然使用之前的 CDN 缓存。这样就降低了需要从网络获取的资源，从而更快一点。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="一个实际的问题举例">一个实际的问题举例<a href="https://shu.moe/posts/web-faster#%E4%B8%80%E4%B8%AA%E5%AE%9E%E9%99%85%E7%9A%84%E9%97%AE%E9%A2%98%E4%B8%BE%E4%BE%8B" class="hash-link" aria-label="一个实际的问题举例的直接链接" title="一个实际的问题举例的直接链接" translate="no">​</a></h2>
<p>我就职于一家设备生产公司，公司的官网挂着茫茫多不同型号设备的宣传页面。曾经我也是一个迷信大公司流行技术的实习生，人家说 Next.js 是最佳实践，整一个！人家说 SSR 渲染快，也整一个。一切看上去都很美好。<br>
<!-- -->随着公司规模的逐渐扩大，设备的页面也随之增多，我网站的访问量慢慢的变高了。然后我发现服务器总是会内存不足，我只能先增加内存，做一个把挂掉服务拉起来的守护进程，然后仔细检查我遇到的问题。<br>
<!-- -->回顾一下我的业务场景和技术方案，我的展示内容其实没有动态需求，是可以做纯静态站的。运行 SSR 服务一个是会多花钱，一个是，他引入了不确定因素，可能因为服务器压力导致宕机。</p>
<p>我决定做改版，改成 SSG 生成静态文件，走 CDN 提供站点内容的方式。</p>
<p>第一个问题，旧的页面那么多，改一下都要设计组同事和业务方确认，没办法处理的。那怎么和新的页面并存呢？弄个服务器分流，按链接接到新旧两个项目里。<br>
<!-- -->第二个问题，怎么能让老板理解我的成绩呢？我找了一个 web 自动化测试工具，用代码拉起浏览器，访问我的页面，检查从请求发起，到页面内容展示出来，需要的时间。访问量最高的是首页，改他。本地跑起来两个服务，用自动化工具重复访问两个服务的首页，对比时间差别。你别管快多少，反正是快了。<br>
<!-- -->第三个问题，这个问题是通过服务崩溃发现的，那其他页面会存在类似的问题吗？这真的是一个需要关注的场景吗？可以加一个问题监控和追踪平台，保持持续关注，比如 <a href="https://github.com/getsentry/sentry" target="_blank" rel="noopener noreferrer" class="">sentry</a>。</p>
<p>嗯，问题解决，下班！</p>
<blockquote>
<p>有关于 IETF 各种关于 HTTP Cache 的定义，可以参考两个库的实现
<a href="https://github.com/kornelski/http-cache-semantics" target="_blank" rel="noopener noreferrer" class="">https://github.com/kornelski/http-cache-semantics</a>
<a href="https://github.com/nodejs/undici" target="_blank" rel="noopener noreferrer" class="">https://github.com/nodejs/undici</a> 对着 undici 的 interceptor API 写一个 in-memory cache handler</p>
</blockquote>]]></content:encoded>
            <category>前端</category>
        </item>
    </channel>
</rss>