Angular 5应用中如何确保JavaScript与CSS文件被浏览器缓存?
刚接触Angular 5碰到这个缓存问题太正常了,其实Angular CLI本身已经帮我们铺垫了关键一步,但要让浏览器稳稳缓存vendor.bundle、main.bundle这些文件,还得结合服务器端的配置来配合,下面我给你拆解清楚:
1. 先开启Angular CLI的文件名哈希(重中之重)
你可能没注意,Angular CLI在生产构建时会自动给bundle文件加上唯一哈希值(比如vendor.a1b2c3.bundle.js),这个哈希值会跟着代码内容变化——只要你改了代码,哈希就变,文件名也就变了。
为什么这个很重要?因为如果文件名固定,浏览器缓存后就不会再请求新文件,哪怕你更新了代码用户也看不到。有了哈希文件名,我们就能放心让浏览器长期缓存旧的bundle文件,新代码发布后,用户会加载新的哈希文件名的文件,完全不冲突。
- 开启方式很简单:直接用生产构建命令就行:
ng build --prod,Angular 5的--prod模式默认就会开启outputHashing,生成带哈希的文件名。 - 如果你需要确认配置,可以打开旧版的
.angular-cli.json(Angular 5用的是这个,不是后来的angular.json),找到defaults.build.outputHashing,确保它的值是all或者bundles,不过一般不用改,--prod已经帮你设好了。
2. 服务器端配置Cache-Control头部(你猜的没错!)
前端代码没法控制HTTP响应头,所以必须在你部署的服务器上设置Cache-Control,告诉浏览器哪些文件可以长期缓存。不同服务器的配置方式不一样,我给你几个常见的例子:
Nginx配置
在你的站点配置块里添加这段规则:
# 给静态资源设置长期缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; # 缓存1年 add_header Cache-Control "public, immutable"; }
immutable这个参数很有用,它告诉浏览器:这个文件一旦缓存就不会再变,不用每次都发验证请求(比如If-Modified-Since),因为我们已经用了哈希文件名,只要文件名不变,内容就绝对不变。
Apache配置
在项目根目录的.htaccess文件里添加:
<FilesMatch "\.(js|css|png|jpg|jpeg|gif|ico|svg)$"> Header set Cache-Control "public, max-age=31536000, immutable" </FilesMatch>
max-age=31536000就是1年的秒数,和上面Nginx的expires 1y效果一样。
Node.js(Express)配置
如果你的服务器是用Express写的,添加这段静态文件中间件:
app.use(express.static('dist', { maxAge: '1y', setHeaders: (res, path) => { // 只给js、css等bundle文件加immutable头部 if (path.endsWith('.js') || path.endsWith('.css')) { res.setHeader('Cache-Control', 'public, immutable'); } } }));
3. 一定要注意index.html的缓存!
这里有个坑:index.html是你的应用入口,绝对不能给它设置长期缓存!如果index.html被缓存了,用户即使访问站点,也会加载旧的index.html,里面引用的还是旧的哈希bundle文件,等于白更新了代码。
所以要给index.html设置禁用强缓存的规则:
- Nginx示例:
location = /index.html { expires -1; add_header Cache-Control "no-cache, no-store, must-revalidate"; }
- Apache示例:
<FilesMatch "index\.html$"> Header set Cache-Control "no-cache, no-store, must-revalidate" </FilesMatch>
这样每次用户访问站点,都会请求最新的index.html,然后根据里面的新哈希bundle地址去加载文件——如果缓存里有对应的哈希文件就直接用,没有就请求新的,完美平衡缓存和更新。
总结一下
核心就是三个步骤:
- 用
ng build --prod生成带哈希的bundle文件名 - 在服务器端给bundle文件设置长期的
Cache-Control缓存 - 禁止index.html的强缓存,保证入口文件总是最新的
这样配置后,用户第一次访问会加载所有文件,之后再访问就只会加载index.html,bundle文件全部从浏览器缓存里取,既提升了加载速度,又能保证代码更新后用户能拿到最新版本。
内容的提问来源于stack exchange,提问作者jazza1000

