文章目录
- [1. 动态哈希命名的基本思路](#1. 动态哈希命名的基本思路)
- [2. 具体实现](#2. 具体实现)
-
- [2.1 Vite/Webpack 配置动态哈希](#2.1 Vite/Webpack 配置动态哈希)
- [2.2 HTML 文件中动态引用](#2.2 HTML 文件中动态引用)
-
- 手动引用
- [使用 index.html 模板动态插入](#使用 index.html 模板动态插入)
- [2.3 结合 `Cache-Control` 避免缓存穿透](#2.3 结合
Cache-Control
避免缓存穿透) - [2.4 适用于多环境的动态策略](#2.4 适用于多环境的动态策略)
- 总结
在多环境部署中,静态资源缓存穿透是一个常见问题,尤其是当前端或后端的静态资源未正确更新,导致旧版本被意外加载。
对于这种问题,动态哈希命名策略是一种有效的解决方案,通过给资源文件添加哈希值来确保浏览器获取最新版本。注意,一般在打包工具的 production 生产模式下 build 后的产物都会自动使用哈希命名配置,无需手动配置。今天主要是介绍背后的实现原理,以下是具体的实现方式:
1. 动态哈希命名的基本思路
- 在构建时,为静态资源(JS、CSS、图片等)文件名添加基于内容的哈希值(如 MD5、SHA-256)。
- 在 HTML 或配置文件中,引用时使用带有哈希值的文件名,确保每次构建后的新文件名唯一,避免缓存问题。
- 结合
Cache-Control
策略,让浏览器长时间缓存文件,只有当文件内容变更时才会重新下载。
2. 具体实现
2.1 Vite/Webpack 配置动态哈希
在 Vite(或 Webpack)中,可以通过 build.rollupOptions.output
或 output.filename
进行哈希处理:
Vite (vite.config.ts)
ts
import { defineConfig } from 'vite';
export default defineConfig({
build: {
assetsDir: 'assets',
rollupOptions: {
output: {
entryFileNames: 'assets/[name].[hash].js',
chunkFileNames: 'assets/[name].[hash].js',
assetFileNames: 'assets/[name].[hash].[ext]',
}
}
}
});
Webpack (webpack.config.js)
js
module.exports = {
output: {
filename: 'js/[name].[contenthash].js',
chunkFilename: 'js/[name].[contenthash].js',
},
};
这样,每次构建时,生成的
JS/CSS
文件都会带上基于内容的hash
,确保不同版本的文件不会相互覆盖。
2.2 HTML 文件中动态引用
手动引用
在 HTML 中,可以通过 <script>
或 <link>
直接引入带哈希的文件:
html
<script src="/assets/app.abc123.js"></script>
使用 index.html 模板动态插入
如果是 Vite,可以使用 vite-plugin-html
插件:
ts
import { createHtmlPlugin } from 'vite-plugin-html';
export default defineConfig({
plugins: [
createHtmlPlugin({
inject: {
data: {
title: 'My App',
},
},
}),
],
});
在 index.html
中:
html
<script type="module" src="<%= htmlWebpackPlugin.files.js %>"></script>
2.3 结合 Cache-Control
避免缓存穿透
在 nginx
或 CDN
服务器配置 Cache-Control
,让静态资源长期缓存:
nginx
location /assets/ {
expires max;
add_header Cache-Control "public, immutable";
}
immutable
表示文件不会更改,即使304 Not Modified
也不需要重新验证。
同时,确保 index.html
不被缓存,以便引用最新的哈希文件:
nginx
location / {
expires -1;
add_header Cache-Control "no-cache, must-revalidate";
}
2.4 适用于多环境的动态策略
在 vite.config.ts
或 webpack.config.js
中,可以根据环境变量来控制 hash
策略:
ts
const isProduction = process.env.NODE_ENV === 'production';
export default defineConfig({
build: {
rollupOptions: {
output: {
entryFileNames: isProduction ? 'assets/[name].[hash].js' : 'assets/[name].js',
},
},
},
});
这样,在
开发环境
中不会生成哈希,方便调试,而生产环境
则启用哈希。
总结
- 通过
文件名+哈希
方式,确保静态资源变更时不会被缓存拦截。 - 配置
Nginx/CDN
让index.html
不缓存,而JS/CSS
采用长时间缓存。 - 在
Vite/Webpack
结合环境变量
实现多环境适配。
这样就能有效解决缓存穿透问题,让前端资源在多环境部署时始终保持最新!