緩存 緩存如何工作 web中的緩存 web緩存的優勢 web緩存的問題 webpack緩存原理 可以通過命中緩存,以降低網路流量,使網站載入速度更快,然而,如果我們在部署新版本時不更改資源的文件名,瀏覽器可能會認為它沒有被更新,就會使用它的緩存版本。由於緩存的存在,當你需要獲取新的代碼時,就會顯得很 ...
緩存
緩存如何工作
1.當緩存客戶端需要訪問數據時,它首先檢查緩存。當在緩存中找到所請求的數據時,它被稱為緩存命中。
2.如果在緩存中找不到請求的數據 , 稱為緩存未命中的情況,它將從主存儲器中提取並複製到緩存中。如何完成此操作以及從緩存中彈出哪些數據以便為新數據騰出空間取決於系統使用的緩存演算法或策略。
web中的緩存
1. 使用瀏覽器緩存來提高經常訪問的網頁的性能。當您訪問網頁時,請求的文件將存儲在瀏覽器緩存中的計算存儲中。
2. 單擊返回並返回上一頁使您的瀏覽器能夠從緩存中檢索所需的大多數文件,而不是從Web伺服器中重新發送它們。這種方法稱為讀緩存。瀏覽器可以比從網頁重新讀取文件更快地從瀏覽器緩存中讀取數據。
web緩存的優勢
Web內容可以緩存在客戶端、代理伺服器以及伺服器端。研究表明,緩存技術可以顯著地提高WWW性能,它可以帶來以下好處:
(1)減少網路流量,從而減輕擁塞。
(2)降低客戶訪問延遲,其主要原因有:①緩存在代理伺服器中的內容,客戶可以直接從代理獲取而不是從遠程伺服器獲取,從而減小了傳輸延遲②沒有被緩存的內容由於網路擁塞及伺服器負載的減輕而可以較快地被客戶獲取。
(3)由於客戶的部分請求內容可以從代理處獲取,從而減輕了遠程伺服器負載。
(4)如果由於遠程伺服器故障或者網路故障造成遠程伺服器無法響應客戶的請求,客戶可以從代理中獲取緩存的內容副本,使得WWW服務的魯棒性得到了加強。
web緩存的問題
Web緩存系統也會帶來以下問題:
(1)客戶通過代理獲取的可能是過時的內容。
(2)如果發生緩存失效,客戶的訪問延遲由於額外的代理處理開銷而增加。因此在設計Web緩存系統時,應力求做到Cache命中率最大化和失效代價最小化。
(3)代理可能成為瓶頸。因此應為一個代理設定一個服務客戶數量上限及一個服務效率下限,使得一個代理系統的效率至少同客戶直接和遠程伺服器相連的效率一樣。
webpack緩存原理
可以通過命中緩存,以降低網路流量,使網站載入速度更快,然而,如果我們在部署新版本時不更改資源的文件名,瀏覽器可能會認為它沒有被更新,就會使用它的緩存版本。由於緩存的存在,當你需要獲取新的代碼時,就會顯得很棘手。通過必要的配置,以確保 webpack 編譯生成的文件能夠被客戶端緩存,而在文件內容變化後,能夠請求到新的文件。
1.第一步output.filename確保瀏覽器能夠獲取到修改後的文件,原理是[chunkhash]演算法,這樣做是有問題的,這是由於webpack內部的chunk變化引起的
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
- title: 'Output Management'
+ title: 'Caching'
})
],
output: {
- filename: 'bundle.js',
+ filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist')
}
};
2.通過提取模版(Extracting Boilerplate)將 webpack 的樣板(boilerplate)和 manifest 提取出來。分離到單獨的文件中。這樣多次構建manifest文件都不會產生變化,以此來提高緩存命中率,我們還可以將vendor第三方包也打包到單獨的文件中來提高命中率,但是hash還是變化了,不著急
const path = require('path');
+ const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Caching'
- })
+ }),
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'manifest'
+ })
],
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist')
}
};
3.將第三方庫(library)(例如 lodash 或 react)提取到單獨的 vendor chunk 文件中,是比較推薦的做法,這是因為,它們很少像本地的源代碼那樣頻繁修改。因此通過實現以上步驟,利用客戶端的長效緩存機制,可以通過命中緩存來消除請求,並減少向伺服器獲取資源,同時還能保證客戶端代碼和伺服器端代碼版本一致。這可以通過使用新的 entry(入口) 起點,以及再額外配置一個 CommonsChunkPlugin 實例的組合方式來實現:
var path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
- entry: './src/index.js',
+ entry: {
+ main: './src/index.js',
+ vendor: [
+ 'lodash'
+ ]
+ },
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Caching'
}),
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'vendor'
+ }),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest'
})
],
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist')
}
};
模塊標識符(Module Identifiers)
每個 module.id 會基於預設的解析順序(resolve order)進行增量。也就是說,當解析順序發生變化,ID 也會隨之改變。
當前模塊的 ID。module.id === require.resolve("./file.js")
由於修改了module.id的值,vendor分配到的id也發生了變化
main bundle 會隨著自身的新增內容的修改,而發生變化。
vendor bundle 會隨著自身的 module.id 的修改,而發生變化。
manifest bundle 會因為當前包含一個新模塊的引用,而發生變化。
修改文件前id增量變化
[1] ./src/index.js 336 bytes {1} [built]
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
== [4] multi lodash 28 bytes {0} [built]==
修改文件後id增量變化,發現lodash解析順序變化了,4變成了5
[1] ./src/index.js 421 bytes {1} [built]
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
[4] ./src/print.js 62 bytes {1} [built]
==[5] multi lodash 28 bytes {0} [built]==
可以使用兩個插件來解決這個問題。第一個插件是 NamedModulesPlugin,將使用模塊的路徑,而不是數字標識符。雖然此插件有助於在開發過程中輸出結果的可讀性,然而執行時間會長一些。第二個選擇是使用 HashedModuleIdsPlugin,推薦用於生產環境構建:
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/index.js',
vendor: [
'lodash'
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Caching'
}),
+ new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest'
})
],
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist')
}
};
修改前: 修改前,後完全保持一致
[3Di9] ./src/print.js 62 bytes {1} [built]
[3IRH] (webpack)/buildin/module.js 517 bytes {0} [built]
[DuR2] (webpack)/buildin/global.js 509 bytes {0} [built]
==[0] multi lodash 28 bytes {0} [built]==
[lVK7] ./src/index.js 421 bytes {1} [built]
修改後:
[3IRH] (webpack)/buildin/module.js 517 bytes {0} [built]
[DuR2] (webpack)/buildin/global.js 509 bytes {0} [built]
== [0] multi lodash 28 bytes {0} [built]==
[lVK7] ./src/index.js 427 bytes {1} [built]