从零开始掌握Rewrite重写规则的核心原理与实际应用
优化前:卡得不行
最近接手了一个项目,页面加载速度慢到怀疑人生。首屏加载时间居然要5秒多,用户反馈说点个按钮都要等半天,体验简直糟糕透了。尤其是路由切换的时候,整个页面都会卡一下,看着CPU占用率飙到100%,我也是服了。
一开始我以为是后端接口的问题,结果用Chrome DevTools抓了一下网络请求,发现接口响应时间其实还可以,平均在300ms左右。那问题肯定出在前端了。试了几个页面,发现每次路由切换都会重新加载一堆重复的资源,比如CSS、JS文件,甚至图片也是一样。
找到瓶颈了!
后来仔细看了下项目的配置文件,发现问题出在路由的Rewrite规则上。原来的规则写得太随意,导致每次路由切换时都会触发不必要的重定向。比如:
// 优化前的Rewrite规则
server {
location / {
rewrite ^/(.*)$ /index.html last;
}
}
这段代码看着简单,但问题可不小。rewrite指令直接把所有请求都重定向到了index.html,虽然能实现SPA(单页应用)的功能,但代价就是每次都得重新加载资源,尤其是那些静态文件。
为了验证我的猜测,我用Lighthouse跑了一下性能测试,果然“First Contentful Paint”和“Time to Interactive”这两项得分特别低。而且Network面板里显示,很多文件都被重复下载了,浪费了大量的带宽和时间。
优化思路:从Rewrite入手
既然问题出在Rewrite规则上,那就从这里下手吧。我试了几种方案,最后发现通过精准匹配和缓存策略来优化Rewrite规则效果最好。
首先,我把Rewrite规则改成了更精细的匹配方式,避免所有请求都一股脑地重定向到index.html:
// 优化后的Rewrite规则
server {
location / {
try_files $uri $uri/ /index.html;
}
}
这里的try_files指令会先尝试匹配具体的文件或目录,如果找不到,才会重定向到index.html。这样一来,静态资源就不会被误重定向了,减少了重复加载。
接着,我还加了个缓存策略,确保静态资源不会每次都被重新下载:
location ~* .(jpg|jpeg|png|gif|ico|css|js|pdf|woff|woff2|ttf|svg)$ {
expires 365d;
add_header Cache-Control "public, immutable";
}
这个配置会让浏览器对这些静态资源进行长期缓存,下次访问时直接从本地读取,省去了网络传输的时间。
优化后:流畅多了
改完之后,我重新跑了一遍Lighthouse测试,结果让我很满意:
- 首屏加载时间从5秒降到了800毫秒左右
- 交互时间从4.5秒降到了1.2秒
- 静态资源的重复加载次数减少了90%
最直观的感受就是,路由切换时再也不卡了,用户体验提升了一大截。尤其是在移动设备上,优化前页面滚动时经常掉帧,优化后基本感受不到延迟了。
踩坑提醒:这三点一定注意
在这个过程中我也踩了不少坑,分享出来给大家避雷:
- 缓存时间设置不当:一开始我把静态资源的缓存时间设得太短,只有7天,结果发现效果不明显。后来改成一年(365天),才真正发挥出了缓存的优势。
- 服务端配置问题:如果你用的是Nginx,记得重启服务才能让新配置生效。我当时改完配置忘了重启,折腾了半天才发现问题。
- 动态内容缓存:别把API接口或者动态内容也加上长期缓存,不然会导致数据更新不及时。可以用
Cache-Control: no-cache来避免这个问题。
性能数据对比
最后再贴一下优化前后的关键数据对比,方便大家参考:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 首屏加载时间 | 5秒 | 800毫秒 |
| 交互时间 | 4.5秒 | 1.2秒 |
| 静态资源重复加载次数 | 多次 | 几乎为零 |
可以看到,优化效果还是很显著的。当然,这个方案也不是完美的,比如如果静态资源更新了,用户可能需要手动刷新才能看到最新版本。不过整体来说,这个方案简单有效,适合大多数SPA项目。
以上是我的优化经验
总的来说,这次优化的核心就是通过改进Rewrite规则和添加缓存策略来减少不必要的资源加载。希望我的踩坑经验能帮到你。如果你有更好的方案,欢迎评论区交流!
