事實上, 只有
10%-20%
的最終用戶響應時間是發在從Web服務器獲取HTML文檔並傳送到瀏覽器中的。若是但願可以有效地減小頁面的響應時間,就必須關注剩餘80%-90%
的最終用戶體驗。 --Steve Soudersjavascript
在這篇博客中,我根據工做中的實際項目經驗和一些測試的經驗中總結出了前端頁面在性能上優化方案。其中一些經驗吸取自《高性能網站建設指南》Steve Souders 著 電子工業出版社。css
遵循HTML規範
,將樣式表放在頭部,能夠有效避免白屏
和無樣式內容的閃爍
。<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<!-- 使用link標籤將樣式表放在文檔的HEAD中 -->
<link rel="stylesheet" href="example.css">
</head>
<body></body>
</html>
複製代碼
將腳本放在頂部會形成的影響: 腳本阻塞對其後面內容的顯示
; 腳本會阻塞對其後面組件的下載
;html
將腳本放在底部</body>
標籤以前, 相似於document.body.appendChild(yourScript), 不會阻塞頁面內容的呈現,並且頁面中的可視組件能夠儘早下載。前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<link rel="stylesheet" href="example.css">
</head>
<body>
<!-- 將腳本放在底部 -->
<script src="example.js"></script>
</body>
</html>
複製代碼
將
多個圖片
合成一張圖片
,經過background-position來定位所須要的圖片。每次請求的話只須要請求一張圖片
減小http請求。(若是使用圖標的話建議使用svg,也可使用iconfont)vue
<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4SUJRXhpZgAATU> 複製代碼
多個小文件
中,會下降性能
,每一個文件都會致使一個額外的
HTTP請求Good
java
<link rel="stylesheet" href="example.css">
<script src="example.js"></script>
複製代碼
bad
node
<style> // code </style>
<script> // code </script>
複製代碼
能夠配置緩存
有利於組件重用
CDN是構建在網絡之上的內容分發網絡,依靠部署在
各地的邊緣服務器
,經過中心平臺的負載均衡
、內容分發
、調度
等功能模塊,使用戶就近獲取所需內容,下降網絡擁塞,提升用戶訪問響應速度和命中率。CDN的關鍵技術主要有內容存儲
和分發技術
。--摘自百度百科webpack
經過CDN引入的資源目前基本都是使用目前最新的HTTP2協議
,因此在性能上能夠作到極致優化,感謝CDN。ios
gzip壓縮能夠節省
50%-70%
的網絡開銷
瀏覽器支持的壓縮類型能夠經過network的Accept-Encoding:
gzip
,deflate
來查看。支持deflate的瀏覽器也支持gzip,但不少瀏覽器支持gzip卻不支持deflate
,所以gzip是最理想的壓縮方法
webpack
項目能夠看下面的Vue首屏加載時間優化
方案裏的gzip壓縮// npm install compression --save-dev
const compression = require('compression')
複製代碼
前端打包壓縮的有grunt,gulp,webpack,能夠對HTML,CSS,Javascript代碼壓縮
本文中使用
nginx
服務器進行相關配置,使用apache
一樣能夠作到相關優化,具體操做請另Google
gzip
壓縮gzip on; # 開啓Gzip
gzip_static on; # 開啓靜態文件壓縮
gzip_min_length 1k; # 不壓縮臨界值,大於1K的才壓縮
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss; # 進行壓縮的文件類型
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
複製代碼
HTTP2在前端性能上主要表如今:請求和響應的多路複用、頭部壓縮
我的站點相關配置
nginx配置
location ~.*\.(svg|woff|js|css){
root /yourFilePath;
expires 1d;
}
複製代碼
Expires
頭來告訴Web客戶端它可使用一個組件的當前副本,直到指定的時間爲止 HTTP規範中簡要地稱該頭爲「在這一日期時間以後,響應將被認爲是無效的」。它在HTTP響應中發送expires: Thu, 30 May 2019 20:51:42 GMT
複製代碼
強緩存cache-control: max-age
server {
add_header Cache-Control max-age=72000;
}
複製代碼
在解釋緩存如何很好地改善傳輸性能以前,須要說起除了Expires 頭以外的另外一種選擇。HTTP 1.1引入了Cache-Control頭來克服Expires頭的限制
由於Expires頭使用一個特定的時間,它要求服務器和客戶端的時鐘嚴格同步
。另外,過時日期須要常常檢查,而且一旦將來這天到來了,還須要在服務器配置中提供個新的日期。
Cache-Control使用max-age指令指定組件被緩存多久, 若是從組件被請求開始過去的秒數少於max-age,瀏覽器就使用緩存的版本,這就避免了額外的HTTP請求。一個長久的max-age頭能夠將刷新窗設置爲將來10年
。
Cache-Control: max-age=315360000
複製代碼
Expires 和Cache-Control max-age.若是二者同時出現,HTTP規範規定max-age指令將重寫Expires頭
。
建議使用Cache-Control max-age
,若是使用expires你須要擔憂它帶來的時鐘同步
和配置維護
問題。
Vue官方文檔的Expires相關配置
瀏覽器必須產生這個HTTP請求,執行有效性檢查, 但這仍
比簡單地下載全部已過時的組件效率要高
(對比強緩存
)。若是瀏覽器緩存中的組件是有效的(即它可以和原始服務器上的組件相匹配),原始服務器不會返回整個內容,而是返回一個304 Not Modifed
狀態碼。
附:Vue首屏加載時間過長詳細優化方案
首先附一張優化事後的圖
首屏加載時間
從原來的10s
到2s
,測試的我的站點
注:我在優化vue項目的時候使用的是
vue@2.6.6
,vue-cli@3.4
。 若是是cli2的項目影響也不大,優化的方案是結合服務端和webpack的。
vue-cli腳手架默認配置已經大幅度優化了前端總體的性能,在此基礎上,我又使用了三個優化項增長了大幅度提高
結合服務器相關優化第一條:開啓gzip壓縮
下面是前端項目中vue.config.js
中的配置
// 須要 npm install compression-webpack-plugin --save-dev
const CompressionWebpackPlugin = require('compression-webpack-plugin')
// 定義當前環境
const ENV = process.env.NODE_ENV || 'development'
module.exports = {
configureWebpack: config => {
// 若是是生產環境的話,開啓壓縮
if (ENV === 'production') {
// 參數配置文檔: https://www.webpackjs.com/plugins/compression-webpack-plugin/
config.plugins.push(new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.(js|css|html)$/,
threshold: 10240,
minRatio: 0.8
}))
}
}
}
複製代碼
在
index.html
文件中經過環境來判斷是否引入cdn文件,在vue.config.js
文件中webpack經過環境判斷是否使用cdn引入文件的全局變量
webpack
和index.html
進行相關配置第一步 配置vue.config.js
,只須要在剛纔配置Gzip壓縮的基礎上再加一段代碼
:
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const ENV = process.env.NODE_ENV || 'development'
module.exports = {
configureWebpack: config => {
if (ENV === 'production') {
config.plugins.push(new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.(js|css|html)$/,
threshold: 10240,
minRatio: 0.8
}))
// 配置externals就是當使用CDN進入的js文件在當前項目中能夠引用
// 好比在開發環境引入的vue是import Vue from 'vue', 這個大寫的Vue就是對應的下面的大寫的Vue
config.externals = {
'vue': 'Vue',
'vue-router': 'VueRouter',
'axios': 'axios'
}
}
}
}
複製代碼
第二步 配置index.html
,在body裏使用EJS語法判斷是否爲生產環境
<body>
<div id="app"></div>
<% if (NODE_ENV === 'production') { %>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script>
<% } %>
</body>
複製代碼
devtool | webpack中文網 你能夠根據官網來對開發環境和生產環境進行詳細配置
固然也能夠像我同樣直接productionSourceMap: false
幹掉生產環境的sourceMap
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const ENV = process.env.NODE_ENV || 'development'
module.exports = {
configureWebpack: config => {
if (ENV === 'production') {
config.plugins.push(new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.(js|css|html)$/,
threshold: 10240,
minRatio: 0.8
}))
config.externals = {
'vue': 'Vue',
'vue-router': 'VueRouter',
'axios': 'axios'
}
}
},
// 禁用生產環境的sourceMap
productionSourceMap: false
}
複製代碼
請參考服務端優化第二條
更多更詳細的優化方案詳細能夠參考雅虎軍規; 開頭提到的《高性能網站建設指南》
前端性能優化相當重要,文中說起的是我認爲比較重要的幾點,之後遇到更好的方案會補充進來。固然你也能夠在評論區留言咱們一塊兒探討,有錯誤的地方歡迎指出。