網站的性能的指標:
- 白屏時間
- 首屏時間
- 整頁時間
- DNS時間
- CPU佔用率
一、網絡傳輸性能優化
重定向→拉取緩存→DNS查詢→建立TCP鏈接→發起請求→接收響應→處理HTML元素→元素加載完成。
(1)設置瀏覽器緩存
- 去除network面板頂部的Disable cache 勾選,查看緩存數據來源(from memory cache 和 from
disk cache) - 在瀏覽器接收到服務器響應後,會檢測響應頭部(Header),如果有Etag字段,那麼瀏覽器就會將本次緩存寫入硬盤中。
- nginx配置緩存
etag on; //開啓etag驗證
expires 7d; //設置緩存過期時間爲7天
4. 爲我們的靜態資源添加md5 hash後綴,避免資源更新而引起的前後端文件無法同步的問題。
(2)資源打包壓縮
瀏覽器緩存工作,只有在用戶第二次訪問我們的頁面才能起到效果,如果要在用戶首次打開頁面就實現優良的性能,必須對資源進行優化。
優化措施:
- 減少請求數
- 減小請求資源體積
- 提升網絡傳輸速率
對上線文件進行自動化打包編譯時,通常都需要打包工具:
webpack,Gulp和Grunt、Parcel
①JS壓縮
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true // set to true if you want JS source maps
}),
...Plugins
]
}
②HTML壓縮:
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'
})
③提取公共資源
splitChunks: {
cacheGroups: {
vendor: { // 抽離第三方插件
test: /node_modules/, // 指定是node_modules下的第三方包
chunks: 'initial',
name: 'common/vendor', // 打包後的文件名,任意命名
priority: 10 // 設置優先級,防止和自定義的公共代碼提取時被覆蓋,不進行打包
},
utils: { // 抽離自定義公共代碼
test: /\.js$/,
chunks: 'initial',
name: 'common/utils',
minSize: 0 // 只要超出0字節就生成一個新包
}
}
}
④提取css並壓縮:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module: {
rules: [..., {
test: /\.css$/,
exclude: /node_modules/,
use: [
_mode === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader, {
loader: 'css-loader',
options: {
importLoaders: 1
}
}, {
loader: 'postcss-loader',
options: {
ident: 'postcss'
}
}
]
}]
}
⑤將webpack開發環境修改爲生產環境:
上線時不需要這部分內容,通過配置剔除:
devtool: 'false'
⑥在服務器上開啓Gzip傳輸壓縮,它能將我們的文本類文件體積壓縮至原先的四分之一
gzip on;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
不要對圖片文件進行Gzip壓縮!(gzip_types 把圖片的相關項去掉)
(3)圖片資源優化
資源打包壓縮,只是停留在了代碼層面,而在我們實際開發中,真正佔用了大量網絡傳輸資源的,並不是這些文件,而是圖片
①不要在HTML裏縮放圖像
錯誤做法: 一個200✖200的圖片容器內直接使用一張400✖400的圖片
缺點:一張200KB的圖片和2M的圖片的傳輸時間會是200m和12s的差距
②使用雪碧圖(CSS Sprite)
可以使用插件webpack-spritesmith 插件
缺點:必須知道位置,維護不方便
③使用字體圖標(iconfont)
常用: icomoon 和 阿里圖標 兩個網站
icomoon 和 阿里圖標 這個網站也爲我們提供了將SVG圖片自動轉化成CSS樣式的功能,然後進行引入~
④使用WebP
WebP格式,是谷歌公司開發的一種旨在加快圖片加載速度的圖片格式。圖片壓縮體積大約只有JPEG的2/3,並能節省大量的服務器帶寬資源和數據空間。
⑤使用網絡傳輸性能檢測工具——Page Speed
chrome還爲我們準備好了一款監測網絡傳輸性能的插件——Page Speed,測試網絡傳輸性能了
對測試網站的性能瓶頸提出完整的建議,我們可以根據它的提示進行優化工作。
⑥使用CDN
Linux下使用命令$ traceroute targetIp 或者在Windows下使用批處理 > tracert targetIp,都可以定位用戶與目標計算機之間經過的所有路由器,不言而喻,用戶和服務器之間距離越遠,經過的路由器越多,延遲也就越高。使用CDN的目的之一便是解決這一問題,當然不僅僅如此,CDN還可以分擔IDC壓力。
我們搭建不起來CDN的,不過我們可以使用各大企業提供的服務,諸如騰訊雲等,阿里雲,等等配置也十分簡單。
二、頁面渲染性能優化
①瀏覽器渲染
Chrome(現在使用的是Blink引擎)
Safari使用的Webkit引擎,
Firefox使用的Gecko引擎,指的就是渲染引擎。
而在渲染引擎內,還包括着我們的HTML解釋器(渲染時用於構造DOM樹)、CSS解釋器(渲染時用於合成CSS規則)還有我們的JS解釋器。
②DOM渲染層與GPU硬件加速
一個頁面是有許多許多層級組成的,他們就像千層麪那樣,你能想象出這個頁面實際的樣子嗎?
佈局是由CPU處理的,而繪製則是由GPU完成的
③重排與重繪
重排(reflow):渲染層內的元素佈局發生修改,都會導致頁面重新排列,比如窗口的尺寸發生變化、刪除或添加DOM元素,修改了影響元素盒子大小的CSS屬性(諸如:width、height、padding)。
重繪(repaint):繪製,即渲染上色,所有對元素的視覺表現屬性的修改,都會引發重繪。
重排是由CPU處理的,而重繪是由GPU處理
CPU的處理效率遠不及GPU,並且重排一定會引發重繪,而重繪不一定會引發重排。
④優化策略
(1)CSS屬性讀寫分離
減少重排和重排,就是不用JS去操作元素樣式,這也是我最推薦的。
(2)通過切換class或者style.csstext屬性去批量操作元素樣式(或者 css module 等模塊化CSS),vue在style中添加 scoped
(3)DOM元素離線更新
當對DOM進行相關操作時,例如innerHTML、appendChild等都可以使用Document Fragment對象進行離線操作,帶元素“組裝”完成後再一次插入頁面,或者使用display:none 對元素隱藏,在元素“消失”後進行相關操作。
(4)將沒用的元素設爲不可見:visibility: hidden,這樣可以減小重繪的壓力,必要的時候再將元素顯示。
(5)壓縮DOM的深度
一個渲染層內不要有過深的子元素,少用DOM完成頁面樣式,多使用僞元素或者box-shadow取代
(6)圖片在渲染前指定大小
因爲img元素是內聯元素,所以在加載圖片後會改變寬高,嚴重的情況會導致整個頁面重排,所以最好在渲染前就指定其大小,或者讓其脫離文檔流。
(7)動畫元素採取硬件加速
三、JS阻塞性能
- 內存泄漏
- 代碼中誤寫了死循環
常見錯誤寫法:
while(true){console.log("1111");}
while(1){console.log("1111");}
四、負責均衡
① Node.js處理IO密集型請求
“高內聚低耦合”的思想,你也可以用模塊化的思想去理解,前後解耦就相當與把一個項目分成了前端和後端兩個大模塊,中間通過接口聯繫起來,分別進行開發。
② pm2實現Node.js“多線程”
node一般都是單線程,但是可以通過pm2 實現多線程。
pm2能啓動多個node.js服務,並且它能夠自動控制負載均衡,會自動將用戶的請求分發至壓力小的服務進程上處理。
安裝 && 使用:
- 安裝
$ npm i pm2 -g
- 在build文件夾內添加了pm2.json文件,這是pm2的啓動配置文件,我們可以自行配置相關參數
- 上線時輸入命令
$ pm2 start pm2.json
即可
③ nginx搭建反向代理
所謂代理就是我們通常所說的中介,網站的反向代理就是指那臺介於用戶和我們真實服務器之間的服務器(說的我都拗口了),它的作用便是能夠將用戶的請求分配到壓力較小的服務器上,其機制是輪詢。
nginx模塊被分爲三大類:
handler、filter和upstream.而其中的upstream模塊,負責完成完成網絡數據的接收、處理和轉發,也是我們需要在反向代理中用到的模塊。
(1)upstream配置信息:
upstream關鍵字後緊跟的標識符是我們自定義的項目名稱,通過一對花括號在其中增添我們的配置信息。
ip_hash 關鍵字
:控制用戶再次訪問時是否連接到前一次連接的服務器
server關鍵字
:我們真實服務器的地址,這裏的內容肯定是需要我們去填寫的,不然運維怎麼知道你把項目放在那個服務器上了,也不知道你封裝了一層node而得去監聽3000端口。
(2)server配置信息
server是nginx的基本配置,我們需要通過server將我們定義的upstream應用到服務器上。
listen關鍵字
:服務器監聽的端口
location關鍵字
:和我們之前在node層說到的路由是起同樣的功能,這裏是把用戶的請求分配到對應的upstream上