webpack + express 實現文件精確緩存

因爲最近開發的我的博客(Vue + node)在使用過程當中,發現網絡加載有點慢,因此打算對它進行一次優化。本次優化的目標以下:html

  1. index.html 設置成 no-cache,這樣每次請求的時候都會比對一下 index.html 文件有沒變化,若是沒變化就使用緩存,有變化就使用新的 index.html 文件。
  2. 其餘全部文件一概使用長緩存,例如設置成緩存一年 maxAge: 1000 * 60 * 60 * 24 * 365
  3. 前端代碼使用 webpack 打包,根據文件內容生成對應的文件名,每次從新打包時只有內容發生了變化,文件名纔會發生變化。

以上三點結合,就能實現文件的精確緩存。前端

換句話說,在一年內,若是個人我的博客沒有進行任何更新,那同一臺電腦在這段時間內訪問網站不會發起任何請求;若是有某個文件更新了,只會請求新的文件,舊的文件依舊從緩存讀取。node

小知識webpack

  • max-age: 設置緩存存儲的最大週期,超過這個時間緩存被認爲過時(單位秒)。在這個時間前,瀏覽器讀取文件不會發出新請求,而是直接使用緩存。
  • 指定 no-cache 表示客戶端能夠緩存資源,每次使用緩存資源前都必須從新驗證其有效性。

webpack 打包

根據文件內容生成文件名

經過配置 output 的 filename 屬性能夠實現這個需求。filename 屬性的值選項中有一個 [contenthash],它將根據文件內容建立出惟一 hash。當文件內容發生變化時,[contenthash] 也會發生變化。git

output: {
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].js',
    path: path.resolve(__dirname, '../dist'),
},

提取第三方庫

因爲引入的第三方庫通常都比較穩定,不會常常改變。因此將它們單獨提取出來,做爲長期緩存是一個更好的選擇。
這裏須要使用 webpack4 的 splitChunk 插件 cacheGroups 選項。github

optimization: {
      runtimeChunk: {
        name: 'manifest' // 將 webpack 的 runtime 代碼拆分爲一個單獨的 chunk。
    },
    splitChunks: {
        cacheGroups: {
            vendor: {
                name: 'chunk-vendors',
                test: /[\\/]node_modules[\\/]/,
                priority: -10,
                chunks: 'initial'
            },
            common: {
                name: 'chunk-common',
                minChunks: 2,
                priority: -20,
                chunks: 'initial',
                reuseExistingChunk: true
            }
        },
    }
},
  • test: 用於控制哪些模塊被這個緩存組匹配到。原封不動傳遞出去的話,它默認會選擇全部的模塊。能夠傳遞的值類型:RegExp、String和Function;
  • priority:表示抽取權重,數字越大表示優先級越高。由於一個 module 可能會知足多個 cacheGroups 的條件,那麼抽取到哪一個就由權重最高的說了算;
  • reuseExistingChunk:表示是否使用已有的 chunk,若是爲 true 則表示若是當前的 chunk 包含的模塊已經被抽取出去了,那麼將不會從新生成新的。
  • minChunks(默認是1):在分割以前,這個代碼塊最小應該被引用的次數(譯註:保證代碼塊複用性,默認配置的策略是不須要屢次引用也能夠被分割)
  • chunks (默認是async) :initial、async和all
  • name(打包的chunks的名字):字符串或者函數(函數能夠根據條件自定義名字)

除了提取第三方庫外,結合 Vue 使用 import 動態引入組件還能實現按需加載。web

express 設置

app.use((req, res, next) => { // 將 index.html 設爲 no-cache
     if(req.url == '/') {
         res.setHeader('Cache-control', 'no-cache')
     }

     next()
 })

 app.use(express.static('dist', {
     etag: false,
     maxAge: 1000 * 60 * 60 * 24 * 365, // 緩存一年
 })) // 將dist設爲根目錄

詳細的代碼能夠看一下個人我的博客項目express

參考資料

相關文章
相關標籤/搜索