Vue 打包上線後的快取問題
阿新 • • 發佈:2022-02-23
問題描述 大家用vue腳手架搭建前端工程時,常被快取問題所困擾,具體的表現就是,當程式版本升級時,使用者因為快取訪問的還是老的頁面,然後很多同學很暴力的直接在index.html中加入了這幾行程式碼: <meta http-equiv="Expires" content="0"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-control" content="no-cache"> <meta http-equiv="Cache" content="no-cache"> 升級時快取問題倒解決了,但直接導致了使用者每次訪問你的程式時都要重新請求伺服器,所有的靜態資源都無法用快取了,浪費流量,網路壓力變大。 需求澄清 我們真正需要解決的問題,不是單純的要快取或者不要快取,而是期望視情況而定: 程式每次升級後,使用者都不會因為快取問題而執行的仍然是老的程式。 若程式沒升級,使用者對靜態資源的請求則能用到快取。 解決原理 由於vue腳手架每次打包時,都會將打出的靜態資原始檔名加個雜湊字尾,且index.html中引入時也加了對應的雜湊字尾,所以每個版本的靜態資源都是全新的,不用擔心因升級導致的快取問題。那麼只需讓index.html不快取,且讓其他靜態資源快取,就能實現要求。 讓靜態資源有快取好辦,問題在於怎麼只讓index.html不快取。這裡我們已經不能單單靠前端程式碼來實現了,需要用到伺服器配置。通過伺服器配置,來單獨設定請求index.html時的header,以達到控制快取的目的。 具體實現 如果你是Nginx: Ngnix還是比較容易實現的,只需增加以下配置: location= /index.html { add_header Cache-Control "no-cache, no-store"; } 修改webpack的配置檔案 configureWebpack: { // webpack 配置 output: { // 輸出重構 打包編譯後的 檔名稱 【模組名稱.版本號.時間戳】 filename: `static/js/[name].${process.env.VUE_APP_Version}.${Timestamp}.js`, chunkFilename: `static/js/[name].${process.env.VUE_APP_Version}.${Timestamp}.js` }, } onst Timestamp= new Date().getTime(); // Vue.config.js 配置選項 module.exports = { // publicPath:process.env.NODE_ENV === 'production' ? '/vue_workspac/aihuhuproject/' : '/', //基本路徑 publicPath: '/',//預設的'/'是絕對路徑,如果不確定在根路徑,改成相對路徑'./' // 輸出檔案目錄 outputDir: 'dist', assetsDir: 'static', indexPath: 'index.html', // eslint-loader 是否在儲存的時候檢查 lintOnSave: true, // 生產環境是否生成 sourceMap 檔案 productionSourceMap: false, // css相關配置 css: { // 是否使用css分離外掛 ExtractTextPlugin // extract: true, // 開啟 CSS source maps? sourceMap: false, }, // webpack-dev-server 相關配置 devServer: { open: true,//open 在devServer啟動且第一次構建完成時,自動用我們的系統的預設瀏覽器去開啟要開發的網頁 host: 'localhost',//預設是 localhost。如果你希望伺服器外部可訪問,指定如下 host: '0.0.0.0',設定之後之後可以訪問ip地址 port: 8080, hot: true,//hot配置是否啟用模組的熱替換功能,devServer的預設行為是在發現原始碼被變更後,通過自動重新整理整個頁面來做到事實預覽,開啟hot後,將在不重新整理整個頁面的情況下通過新模組替換老模組來做到實時預覽。 https: false, hotOnly: false,// hot 和 hotOnly 的區別是在某些模組不支援熱更新的情況下,前者會自動重新整理頁面,後者不會重新整理頁面,而是在控制檯輸出熱更新失敗 proxy: { '/api': { target: 'http://localhost:8080', //目標介面域名 secure: false, //false為http訪問,true為https訪問 changeOrigin: true, //是否跨域 pathRewrite: { '^/api': '' //重寫介面 } } }, // 設定代理 before: app => { } }, configureWebpack: { // webpack 配置 output: { // 輸出重構 打包編譯後的 檔名稱 【模組名稱.版本號.時間戳】 filename: `static/js/[name].${process.env.VUE_APP_Version}.${Timestamp}.js`, chunkFilename: `static/js/[name].${process.env.VUE_APP_Version}.${Timestamp}.js` }, }, // 第三方外掛配置 pluginOptions: { // ... } };