文章目錄
- 1. 動態哈希命名的基本思路
- 2. 具體實現
- 2.1 Vite/Webpack 配置動態哈希
- 2.2 HTML 文件中動態引用
- 手動引用
- 使用 index.html 模板動態插入
- 2.3 結合 `Cache-Control` 避免緩存穿透
- 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)
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)
module.exports = {output: {filename: 'js/[name].[contenthash].js',chunkFilename: 'js/[name].[contenthash].js',},
};
這樣,每次構建時,生成的
JS/CSS
文件都會帶上基于內容的hash
,確保不同版本的文件不會相互覆蓋。
2.2 HTML 文件中動態引用
手動引用
在 HTML 中,可以通過 <script>
或 <link>
直接引入帶哈希的文件:
<script src="/assets/app.abc123.js"></script>
使用 index.html 模板動態插入
如果是 Vite,可以使用 vite-plugin-html
插件:
import { createHtmlPlugin } from 'vite-plugin-html';export default defineConfig({plugins: [createHtmlPlugin({inject: {data: {title: 'My App',},},}),],
});
在 index.html
中:
<script type="module" src="<%= htmlWebpackPlugin.files.js %>"></script>
2.3 結合 Cache-Control
避免緩存穿透
在 nginx
或 CDN
服務器配置 Cache-Control
,讓靜態資源長期緩存:
location /assets/ {expires max;add_header Cache-Control "public, immutable";
}
immutable
表示文件不會更改,即使304 Not Modified
也不需要重新驗證。
同時,確保 index.html
不被緩存,以便引用最新的哈希文件:
location / {expires -1;add_header Cache-Control "no-cache, must-revalidate";
}
2.4 適用于多環境的動態策略
在 vite.config.ts
或 webpack.config.js
中,可以根據環境變量來控制 hash
策略:
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
結合環境變量
實現多環境適配。
這樣就能有效解決緩存穿透問題,讓前端資源在多環境部署時始終保持最新!