這是山月關於高級前端進階暨前端工程系列文章的第 M 篇文章 (M 隨便打的,畢竟也不知道能寫多少篇),關於前 M-1 篇文章,能夠從個人 github repo shfshanyue/blog 中找到,若是點進去的話能夠捎帶~點個贊~,若是沒有點進去的話,那就給這篇文章點個贊。今天的文章開始了javascript
本篇文章地址在 前端工程化系列,歡迎訂閱。css
在前端中但凡談到打包,確定要說起到 webpack
,畢竟它如今已是最爲流行的打包工具。但 webpack
更多地是表如今 術
上,因而我決定寫這篇文章,更多地講解一些關於 道
的。html
對於一個前端而言,生產環境的靜態資源優化,它既是面試中的高頻問題,同時也最容易成爲平時工做中的 OKR/KPI。若是你常常致力於優化前端打包說起,必然會對一些數字極爲敏感,好比:前端
lodash
和 react
gzip 後的體積是多少 (定性,能夠給出範圍)moment
時會有什麼問題若是你負責了大家前端項目的打包優化,若是以上問題連一個都不瞭解那麼是說不通的。以我做爲面試官的兩年經驗中,若是候選人對這些問題有所瞭解的話,每每對打包以及webpack的瞭解就會相對深刻一些java
通常談到打包會有兩方面的意思,第一在於提升打包的速度,第二在於對打包後的靜態資源的優化。而對於靜態資源的優化又不只僅是打包說起的縮減。node
對於打包資源優化的整體原則,在於儘量的減小或者延遲模塊的引用。主要遵循如下三點react
Code Splitting
: 按需加載,優化頁面首次加載體積。如根據路由按需加載,根據是否可見按需加載Bundle Splitting
:分包,根據模塊更改頻率分層次打包,充分利用緩存接下來本篇文章將會結合實例分別闡述這三點webpack
第一種方法是減少打包的總體體積。減少打包的整體積有多種方式,這每每也是打包資源優化的着力點,一方面操做性高易於實踐,~另外一方面有具體數據支撐易於寫PPT來晉升~。我從網站性能優化的實踐角度,來分爲如下幾個方面git
代碼壓縮能夠很是可觀地減少資源打包體積,可是它的可操做性空間太小。可操做性低的意思是這一項不太容易出如今晉級評審的PPT上,如同 CDN 在網站性能優化的重要程度同樣,重要但不歸你作(或者傻瓜式配置)。github
它良好的模塊化,以至於 webpack
就自做主張在生產環境中默認把這件事給作了。
那它是如何壓縮代碼的?最典型的兩種方法就是空白符替換以及縮短變量名,如代碼所示,僅僅經過這兩種方式就大大壓縮了 javascript 資源:
// 壓縮前 function sum (first, second) { return first + second; } // 壓縮後 function s(x,y){return a+b}
關於代碼壓縮,能夠參考山月的前端高級進階系列之javascript 代碼的體積是如何被壓縮的
這句話好像是廢話,但它倒是真正有用而且極爲容易實現的一點。
在如下代碼中,對 lodash
這個模塊進行了引入,但在以後的代碼中並沒有使用 lodash
,那在 webpack 中這個模塊還會繼續打包嗎?
很遺憾,仍會對它進行打包。但好消息是這一點優化起來至關簡單。
// 僅僅引入而未在代碼中使用,該模塊仍然會被打包 import _ from 'lodash'
對於這類問題總應該防患於未然,扼殺於搖籃中。eslint
的用武之地來了,它除了統一團隊的代碼風格之外,也用來提升團隊的代碼質量以及性能。
針對這一條,有一個典型的例子是以體積過大而臭名昭著的 moment.js
模塊,它僅僅用於 DateTime
的格式化及各類計算。但你 import
以後它的體積居然達到了 200kb+,gzip 後仍然有 69kb。以致於在 github 上有一個倉庫專門用來介紹如何優化它,
再來一張圖感覺一下它巨大的體積吧:
此時能夠選擇一個可替代它功能,但體積更小的模塊。與 moment.js
API 兼容的 day.js
,它 gzip 後體積僅僅只有 2kb。
當你面對一個巨無霸的,捆綁式的大型模塊時,可能你並不會使用到它的全部的功能,你只須要按照你的需求引入模塊就能夠了。那常常會有哪些巨無霸模塊呢?
如 lodash
(勉強算),antd
,echarts
,我相信這三個模塊對於以 React 爲主的前端工程師都或多或少使用過。對你所須要使用的模塊單獨引入:
import DatePicker from 'antd/es/date-picker'; // for js import 'antd/es/date-picker/style/css'; // for css import get from 'lodash.get'
懶加載,若是面試中提到懶加載的話,大機率面試官此時是想問你關於圖片懶加載的問題。
前端開發中的圖片懶加載如何實現
經過 Code Splitting
能夠只加載當前所須要的核心資源:
他們實現起來均須要額外編寫代碼,因此可操做性中等,可是好在它可以帶來極大的益處,投資回報率較高,操做起來也極爲簡單,接下來就屬於體力活了:
import()
動態加載模塊React.lazy()
動態加載組件lodable-component
動態加載路由,組件或者模塊大部分狀況下,你只要作一個莫得感情的 API 工程師調用以上三個 API 就能夠解決問題,大幅度下降頁面的首次加載體積。可是在前往高級前端工程師的路上,你有可能須要瞭解其中的原理,(有可能並不須要,數據比原理重要) 來作更加精細化的控制,好比針對緩存。
Code Splitting 的原理是什麼?
除了資源體積上的優化,另外一個大的優化就是緩存。單頁應用有一個最好的方面,就是全部資源都是帶有指紋信息的,這意味着全部的資源都是可以設置永久緩存的。
但僅僅如此了嗎?
若是你全部的 js 資源都打包成一個文件,它確實有永久緩存的優點。可是當有一行文件進行修改時,這一個大包的指紋信息發生改變,永久緩存失效。
因此咱們如今須要作到的是:當修改文件後,形成最小範圍的緩存失效,這樣便可以更充分的利用緩存,減少寬帶,減少服務器費用。一個好消息是 webpack
等打包工具雖然在 optimization
上內置了不少性能優化,但它不會幫你作這件事,它並不知道你有哪些模塊,以及這些模塊的重要緊急程度,你終於能夠大展拳腳了。
此時咱們能夠對資源進行分層次緩存的打包方案,這是一個建議方案
webpack-runtime
: 應用中的 webpack
的版本比較穩定,分離出來,保證長久的永久緩存react-runtime
: react
的版本更新頻次也較低vundor
: 經常使用的第三方模塊打包在一塊兒,如 lodash
,classnames
基本上每一個頁面都會引用到,可是它們的更新頻率會更高一些隨着 http2
的發展,特別是多路複用,初始頁面的靜態資源不受資源數量的影響。所以爲了更好的緩存效果以及按需加載,也有不少方案建議把全部的第三方模塊進行單模塊打包。
在 webpack 中,使用 splitChunks.cacheGroups
{ splitChunks: { cacheGroups: { react: { test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, name: 'react', chunks: 'all' }, vendor: { } } }, runtimeChunk: { name: entrypoint => `runtime-${entrypoint.name}`, }, }
毫無疑問在前端中更好地優化打包資源屬於網站性能優化強操做性部分的重中之重,整理下本篇文章關於資源優化的全部內
減少打包的總體體積
Code Splitting
: 按需加載,優化頁面首次加載體積。如根據路由按需加載,根據是否可見按需加載
import()
動態加載模塊React.lazy()
動態加載組件lodable-component
動態加載路由,組件或者模塊Bundle Splitting
:分包,根據模塊更改頻率分層次打包,充分利用緩存掃碼添加個人機器人微信,將會自動(自動拉人程序正在研發中)把你拉入前端高級進階學習羣
我是山月,能夠加我微信
shanyue94
與我交流,備註交流。另外能夠關注個人公衆號【全棧成長之路】