網站性能優化是必須的技能,並且須要長期積累,如下是我本身總結的一些性能優化的策略,主要分爲幾個方面:javascript
瀏覽器在向服務器發起請求前,會先查詢本地是否有相同的文件,若是有,就會直接拉取本地緩存,這和咱們在後臺部署的Redis、Memcache相似,都是起到了中間緩衝的做用,咱們先看看瀏覽器處理緩存的策略:php
瀏覽器默認的緩存是放在內存內的,內存裏的緩存會由於進程的結束或者說瀏覽器的關閉而被清除,而存在硬盤裏的緩存纔可以被長期保留下去。不少時候,咱們在network面板中各請求的size項裏,會看到兩種不一樣的狀態:from memory cache 和 from disk cache,前者指緩存來自內存,後者指緩存來自硬盤。而控制緩存存放位置的,不是別人,就是咱們在服務器上設置的Etag字段。在瀏覽器接收到服務器響應後,會檢測響應頭部(Header),若是有Etag字段,那麼瀏覽器就會將本次緩存寫入硬盤中。css
以Nginx爲例,設置Etaghtml
etag on; //開啓etag驗證
expires 14d; //設置緩存過時時間爲14天
複製代碼
打開咱們的網站,在chrome devtools的network面板中觀察咱們的請求資源,若是在響應頭部看見Etag和Expires字段,就說明咱們的緩存配置成功了。java
在咱們配置緩存時必定要切記,瀏覽器在處理用戶請求時,若是命中強緩存,瀏覽器會直接拉取本地緩存,不會與服務器發生任何通訊,也就是說,若是咱們在服務器端更新了文件,並不會被瀏覽器得知,就沒法替換失效的緩存。因此咱們在構建階段,須要爲咱們的靜態資源添加md5 hash後綴,避免資源更新而引發的先後端文件沒法同步的問題。webpack
咱們以前所做的瀏覽器緩存工做,只有在用戶第二次訪問咱們的頁面才能起到效果,若是要在用戶首次打開頁面就實現優良的性能,必須對資源進行優化。咱們常將網絡性能優化措施歸結爲三大方面:減小請求數、減少請求資源體積、提高網絡傳輸速率。如今,讓咱們逐個擊破:nginx
以Webpack爲例web
new webpack.optimize.UglifyJsPlugin()
複製代碼
new HtmlWebpackPlugin({
template: __dirname + '/views/index.html', // new 一個這個插件的實例,並傳入相關的參數
filename: '../index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
chunksSortMode: 'dependency'
})
複製代碼
咱們在使用html-webpack-plugin 自動化注入JS、CSS打包HTML文件時,不多會爲其添加配置項,這裏我給出樣例,你們直接複製就行。chrome
PS:這裏有一個技巧,在咱們書寫HTML元素的src 或 href 屬性時,能夠省略協議部分,這樣也能簡單起到節省資源的目的。後端
在使用webpack的過程當中,咱們一般會以模塊的形式引入css文件(webpack的思想不就是萬物皆模塊嘛),可是在上線的時候,咱們還須要將這些css提取出來,而且壓縮,這些看似複雜的過程只須要簡單的幾行配置就行
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module: {
rules: [..., {
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: {
loader: 'css-loader',
options: {
minimize: true
}
}
})
}]
}
複製代碼
new webpack.optimize.ModuleConcatenationPlugin()
複製代碼
devtool: shouldUseSourceMap ? 'source-map' : false,
複製代碼
最後,咱們還應該在服務器上開啓Gzip傳輸壓縮,它能將咱們的文本類文件體積壓縮至原先的四分之一,效果立竿見影,仍是切換到咱們的nginx配置文檔,添加以下兩項配置項目:
gzip on;
gzip_types text/plain application/javascriptapplication/x-javascripttext/css application/xml text/javascriptapplication/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
複製代碼
若是你在網站請求的響應頭裏看到這樣的字段,那麼就說明我們的Gzip壓縮配置成功啦:
【!!!特別注意!!!】不要對圖片文件進行Gzip壓縮!不要對圖片文件進行Gzip壓縮!不要對圖片文件進行Gzip壓縮!我只會告訴你效果拔苗助長,至於具體緣由,還得考慮服務器壓縮過程當中的CPU佔用還有壓縮率等指標,對圖片進行壓縮不但會佔用後臺大量資源,壓縮效果其實並不可觀,能夠說是「弊大於利」,因此請在gzip_types 把圖片的相關項去掉。針對圖片的相關處理,咱們接下來會更加具體地介紹。
使用CDN存放靜態資源,避免帶寬爆炸以及加快資源下載.
函數防抖:將幾回操做合併爲一此操做進行。原理是維護一個計時器,規定在delay時間後觸發函數,可是在delay時間內再次觸發的話,就會取消以前的計時器而從新設置。這樣一來,只有最後一次操做能被觸發。
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null)
clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
複製代碼
函數節流:使得必定時間內只觸發一次函數。原理是經過判斷是否到達必定時間來觸發函數。
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
複製代碼
區別: 函數節流無論事件觸發有多頻繁,都會保證在規定時間內必定會執行一次真正的事件處理函數,而函數防抖只是在最後一次事件後才觸發一次函數。 好比在頁面的無限加載場景下,咱們須要用戶在滾動頁面時,每隔一段時間發一次 Ajax 請求,而不是在用戶停下滾動頁面操做時纔去請求數據。這樣的場景,就適合用節流技術來實現。