前端性能優(yōu)化總結(jié)
gzip壓縮
gzip壓縮效率很高,可以達到70%的壓縮率
//npm i -D compression-webpack-plugin 安裝插件依賴
configureWebpack: config => {
const CompressionPlugin = require('compression-webpack-plugin')
config.plugins.push(new CompressionPlugin())
}
去掉console.log
生產(chǎn)環(huán)境中,不需要打印日志。通過對webpack進行配置,打包時自動去掉console.log
//npm i -D terser-webpack-plugin
configureWebpack:config =>{
const TerserPlugin = require('terser-webpack-pulugin')
config.optimzation.minimizer.push(
new TerserPlugin({
extractComments:false,
terserOptions:{compress:{drop_console:true}} //插件配置項 移除console
})
)
}
去除SourceMap
代碼壓縮后進行調(diào)bug定位將非常困難,于是引入sourcemap記錄壓縮前后的位置信息記錄,當產(chǎn)生錯誤時直接定位到未壓縮前的位置,將大大的方便我們調(diào)試。
sourcemap附帶了很多信息,如果build需要生成sourcemap,將會大大降低build的速度,還會增加包的體積。
//vue 中
module.exports = {
productionSourceMap: false,
}
//react中
//打開webpack.config.prod.js
const shouldUseSourceMap = false
CDN
內(nèi)容分發(fā)網(wǎng)絡(luò),它能夠?qū)崟r地根據(jù)網(wǎng)絡(luò)流量和各節(jié)點的連接、負載狀況以及到用戶的距離和響應(yīng)時間等綜合信息將用戶的請求重新導(dǎo)向離用戶最近的服務(wù)節(jié)點上。其目的是使用戶可就近取得所需內(nèi)容,解決
Internet網(wǎng)絡(luò)擁擠的狀況,提高用戶訪問網(wǎng)站的響應(yīng)速度。所以可以通過將資源部署在CDN上來提高響應(yīng)速度,提高用戶體驗
預(yù)渲染
簡單來說,就是將瀏覽器解析JavaScript動態(tài)渲染的工作,在打包階段完成了(只構(gòu)建了靜態(tài)數(shù)據(jù))。換個說法,在構(gòu)建過程中,webpack通過使用prerender-spa-plugin插件生成靜態(tài)結(jié)構(gòu)的html
// 1、安裝prerender-spa-plugin
npm install prerender-spa-plugin --save-dev
// 2、安裝vue-meta-info
npm install vue-meta-info --save-dev
// 3、相關(guān)配置
<!-- webpack.prod.conf.js -->
// 預(yù)渲染配置:在webpack.prod.conf文件中加入
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
// 在 plugins 中加入
new PrerenderSPAPlugin({
// 生成文件的路徑,也可以與webpakc打包的一致。
// 下面這句話非常重要?。?!
// 這個目錄只能有一級,如果目錄層次大于一級,在生成的時候不會有任何錯誤提示,在預(yù)渲染的時候只會卡著不動。
staticDir: path.join(__dirname, '../dist'),
// 對應(yīng)自己的路由文件,比如a有參數(shù),就需要寫成 /a/param1。
routes: ['/', '/first', '/second', '/third', '/fourth',
'/userCenter/userFirst','/userCenter/userSecond','/userCenter/userThird'],
// 這個很重要,如果沒有配置這段,也不會進行預(yù)編譯
renderer: new Renderer({
inject: {
foo: 'bar'
},
// headless: false,
renderAfterDocumentEvent: 'render-event', // 在 main.js 中 document.dispatchEvent(new Event('render-event')),兩者的事件名稱要對應(yīng)上。
args: ['--no-sandbox', '--disable-setuid-sandbox']
})
})
// 4、在main.js中
import MetaInfo from 'vue-meta-info'
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
// 添加mounted,不然不會執(zhí)行預(yù)編譯
mounted () {
document.dispatchEvent(new Event('render-event'))
}
})
注意:路由模式必須為 history ,如果不設(shè)置 history 模式,也能運行和生成文件,每個 index.html 文件的內(nèi)容都會是一樣的
Service Worker
ServiceWorker 是運行在瀏覽器后臺進程里的一段 JS,它可以做許多事情,比如攔截客戶端的請求、向客戶端發(fā)送消息、向服務(wù)器發(fā)起請求等等,其中最重要的作用之一就是離線資源緩存。
ServiceWorker 擁有對緩存流程豐富靈活的控制能力,當頁面請求到 ServiceWorker 時,ServiceWorker 同時請求緩存和網(wǎng)絡(luò),把緩存的內(nèi)容直接給用戶,而后覆蓋緩存
注意:需要HTTPS才能使用ServiceWorker
HTTP緩存
HTTP緩存一般分為兩類:強緩存(本地緩存)、協(xié)商緩存(304緩存)
普通刷新會啟用協(xié)商緩存
在地址欄輸入網(wǎng)址、通過鏈接引入資源等情況下,瀏覽器才啟用強緩存
強緩存(200)。本地緩存是最快速的一種緩存方式,只要資源還在緩存有效期內(nèi),瀏覽器就會直接在本地讀取,不會請求服務(wù)端。在chrome控制臺的Network選項中可以看到該請求返回200的狀態(tài)碼,并且Size顯示from
disk cache或from memory cache。強緩存可以通過設(shè)置兩種 HTTP Header 實現(xiàn):Expires 和
Cache-Control。
協(xié)商緩存(304)。協(xié)商緩存,顧名思義是經(jīng)過瀏覽器與服務(wù)器之間協(xié)商過之后,在決定是否讀取本地緩存,如果服務(wù)器通知瀏覽器可以讀取本地緩存,會返回304狀態(tài)碼,并且協(xié)商過程很簡單,只會發(fā)送頭信息,不會發(fā)送響應(yīng)體。
協(xié)商緩存可以通過設(shè)置兩種 HTTP Header 實現(xiàn):Last-Modified 和 ETag
首先在精確度上,Etag要優(yōu)于Last-Modified
第二在性能上,Etag要遜于Last-Modified,畢竟Last-Modified只需要記錄時間,而Etag需要服務(wù)器通過算法來計算出一個hash值
第三在優(yōu)先級上,服務(wù)器校驗優(yōu)先考慮Etag
緩存優(yōu)先級:Service Worker -> Memory Cache(內(nèi)存緩存) -> Disk Cache(硬盤緩存) -> Push Cache(推送緩存)
Push Cache 只在會話(session)中存在,會話結(jié)束就被釋放,而且緩存時間很短
HTTP2
HTTP2 四個新特性:
多路復(fù)用,無需多個TCP連接,因為其允許在單一的HTTP2連接上發(fā)起多重請求,因此可以不用依賴建立多個TCP連接。
二進制分幀,將所有要傳輸?shù)南⒉捎枚M制編碼,并且會將信息分割為更小的消息塊。
頭部壓縮,用HPACK技術(shù)壓縮頭部,減小報文大小
服務(wù)端推送,服務(wù)端可以在客戶端發(fā)起請求前發(fā)送數(shù)據(jù),換句話說,服務(wù)端可以對客戶端的一個請求發(fā)送多個相應(yīng),并且資源可以正常緩存。
server {
listen 443 ssl http2;
}
資源預(yù)加載
提前加載資源,當用戶需要時,可以直接從本地緩存中渲染。
preload
頁面加載的過程中,在瀏覽器開始主體渲染之前加載
//對sty1e.cs5和 index.js進行pre1oad預(yù)加載
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="index.js" as="script">
prefetch
頁面加載完成后,利用空閑時間提前加載
//對資源進行 prefetch預(yù)加載
<link rel="prefetch" href="next.css">
<link rel="prefetch" href="next.js">
dns-prefetch
//對特定域名進行預(yù)解析
//將靜態(tài)資源只放在一個域名下面,可以有效減少dns的請求
<link rel=”dns-prefetch” href=”//fonts.googleapis.com”>
異步無阻塞加載JS
異步加載 js 文件,并且不會阻塞頁面的渲染。
普通的script標簽在開始解析和解析的過程中,會停止解析dom
defer
<script src="d.js" defer></script> <script src="e.js" defer></script>
在其他同步腳本執(zhí)行后,DOMContentLoaded 事件前 依次執(zhí)行 d.js, e.js。
async
<script src="b.js" async></script>
<script src="c.js" async></script>
當腳本下載完后立即執(zhí)行。(兩者執(zhí)行順序不確定,執(zhí)行階段不確定,可能在 DOMContentLoaded 事件前或者后 )
defer和async都不會停止解析dom
webp
webp 是一種新的圖片格式,它的體積只有只有 jpeg的2/3,將圖片資源大量換成 webp 格式可以加快請求的速度
但是webp存在瀏覽器兼容問題,使用前需要判斷瀏覽器是否支持
loading加載
通過添加加載中狀態(tài),可以讓用戶在視覺上不會覺得慢
可以通過骨架屏加載,在感官上內(nèi)容出現(xiàn)的流暢不突兀
歡迎關(guān)注微信公眾號:猴哥說前端