這幾天我讀了 Webpack實戰:入門、進階與調優,感受收穫挺大的,把讀書筆記發出來,供之後開發時參考,相信對其餘人也有用。css
個人書單html
1.CommonJS 與 ES6 Module 最本質的區別在於前者對模塊依賴的解決是「動態」的,然後者是「靜態」的。動態的含義是:模塊依賴關係的創建發生在代碼運行階段;而靜態則是模塊依賴關係的創建發生在代碼編譯階段。因此 ES6 Module 具備如下幾點優點:1.死代碼檢測和排除。2.模塊變量類型檢查。3.編譯器優化。node
2.在導入一個模塊時,對於 CommonJS 來講獲取的是一份導出值得拷貝,而在 ES6 Module 中則是值的動態映射,而且這個映射是隻讀的。react
3.在 CommonJS 中,若遇到循環依賴咱們沒有辦法獲得預想中的結果;可是在 ES6 Module 中,咱們只須要保證當導入的值被使用時已經設置好正確的導出值,就能夠支持循環依賴。webpack
4.每一個 npm 模塊都有一個入口。當咱們加載一個模塊時,實際上就是加載該模塊的入口文件。這個入口被維護在模塊內部 package.json 文件的 main 字段中。nginx
5.webpack 的 context 字段表示的是基本目錄,能夠理解爲資源入口的路徑前綴,在配置時要求必須使用絕對路徑的形式。默認使用當前目錄。git
6.爲了解決打包體積過大的問題,咱們可使用提取 vendor 的方法。vendor 的意思是「供應商」,在 webpack 中 vendor 通常指的是工程所使用的的庫、框架等第三方模塊集中打包而產生的 bundle。es6
7.在多入口的場景中,咱們須要爲對應產生的每一個 bundle 指定不一樣的名字,webpack 支持使用一種相似模板語言的形式動態地生成文件名。除了[name]
能夠指代 chunk name 之外,還有其它幾種模板變量能夠用於 filename 的配置中。github
8.在 webpack4 之前的版本中,打包資源默認會生成在工程根目錄,所以咱們須要上述配置;而在 webpack4 以後,output.path 已經默認爲 dist 目錄,除非咱們須要更改它,不然沒必要單獨配置。web
9.loader 裏面的 test、exclude、include 本質上屬於對 resource 也就是被加載者的配置,若是想要對 issuer 加載者也增長條件限制,則要額外寫一些配置。
10.webpack 中的 loader 按照執行順序可分爲 pre、inline、normal、post 四種類型,上面咱們直接定義的 loader 都屬於 normal 類型,inline 形式官方已經不推薦使用,而 pre 和 post 則須要使用 enforce 來指定。enforce 的值爲 pre,表明它將在全部正常 loader 以前執行,這樣能夠保證其檢測的代碼不是被其它 loader 更改過的。而 post 表示在全部 loader 以後執行。
11.對於 babel-loader 自己咱們添加了 cacheDirectory 配置項,它會啓用緩存機制,在重複打包未改變過的模塊時防止二次編譯,一樣也會加快打包的速度。cacheDirectory 能夠接收一個字符串類型的路徑來做爲緩存路徑,這個值也能夠爲 true,此時緩存目錄會指向 node_modules/.cache/babel-loader。
12.因爲 @babel/preset-env 會將 es6 module 轉化爲 commonjs 的形式,這會致使 webpack 中的 tree-shaking 特性失效。將 @babel/preset-env 的 modules 配置項設置爲 false 會禁用模塊語句的轉化,而將 es6 module 的語法交給 webpack 自己處理。
13.url-loader 與 file-loader 做用相似,惟一的不一樣在於用戶能夠設置一個文件大小的閾值,當大於該閾值時與 file-loader 同樣返回 publicPath,而小於該閾值時返回文件 base64 形式編碼。
14.在寫自定義 loader 的時候,可使用 this.sync 獲取 callback 函數。callback 函數的3個參數分別是拋出的錯誤、處理後的源碼,以及 source-map。
15.css-loader 在把 css 打包以後,在運行的時候會將其插入到 style 標籤中,可是在生產環境下,咱們但願樣式存在於 css 文件中,這樣更有利於客戶端緩存。而 mini-css-extract-plugin 就是專門用於提取樣式到 css 文件的。而說到 mini-css-extract-plugin 的特性,最重要的就是它支持按需加載 css。
16.Sass 自己是對 css 的語法加強,它有兩種語法,如今使用更多的是 scss。因此你會發現,在安裝和配置 loader 時都是 sass-loader,而實際的文件後綴是 .scss。
17.loader 自己只是編譯核心庫與 webpack 的鏈接器,所以這裏咱們除了 sass-loader 之外還要安裝 node-sass,node-sass是真正用來編譯 scss 的,而 sass-loader 只是起到黏合的做用。值得一提的是,加入咱們想要在瀏覽器的調試工具裏查看源碼,須要分別爲 sass-loader 和 css-loader 單獨添加 source map 的配置項。
18.解決 node-sass 下載較慢的方法是爲其單獨設置一個 cnpm 的鏡像地址,可以使用以下命令:npm config set sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
19.嚴格來講,postcss-loader 不能算是一個 css 預編譯器,它只是一個編譯插件的容器,它的工做模式是接收樣式源代碼並交由編譯插件處理,最後輸出 css。
20.咱們能夠在 autoprefixer 中添加須要支持的特性(如grid)以及兼容哪些瀏覽器(browsers)。
21.postcss 能夠與 cssnext 結合使用,讓咱們在應用中使用最新的css語法特性。
22.使用 css modules 時 css 文件會導出一個對象,咱們須要把這個對象中的屬性添加到 html 標籤上。
23.代碼分片能夠有效下降首屏加載資源的大小,但同時也會帶來新的問題,好比咱們應該對哪些模塊進行分片、分片後的資源如何管理等,這些也是須要關注的。
24.有些時候咱們不但願全部的公共模塊都被提取出來,好比項目中一些組件或工具模塊,雖然被屢次引用,可是可能常常修改,若是將其和 react 這種庫放在一些反而不利於客戶端緩存。這個時候能夠把 minChunks 配置項的值調大一點來解決。
25.minChunks 設置爲 Infinity 的意義有兩個,第一個是咱們只想讓 webpack 提取 vendor 字段寫的幾個模塊,讓提取更加可控;另外一個是可以生成一個僅僅包含 webpack 初始化環境的文件,稱爲 manifest 文件。manifest 文件其實就是各個 chunk 的打包地圖,之前能夠用它來有效解決打包的時候 verdor 包的 chunId 變化的問題。
26.webpack runtime 指的是初始化環境的代碼,如建立模塊緩存對象、聲明模塊加載函數等。
27.CommonChunkPlugin 的不足:1.一個 CommonChunkPlugin 只能提取一個 verdor;2.會多加載一個 manifest 文件;3.會破壞掉原有 chunk 中模塊的依賴關係,致使難以進行更多的優化。而 webpack4 裏面的 optimization.SplitChunks 就是爲了改進 CommonChunkPlugin 而從新設計和實現的代碼分片特性,是 webpack 的內置模塊,能夠直接使用。
28.資源異步加載主要解決的問題是,當模塊數量過多、資源體積過大時,能夠把一些暫時使用不到的模塊延遲加載。這樣使頁面初次渲染的時候用戶下載的資源儘量小,後續的模塊等到恰當的時機再去觸發加載,所以通常也把這種方法叫作按需加載。
29.與正常 es6 的 import 語法不通,經過 import 函數加載的模塊及其依賴會被異步地進行加載,並返回一個 Promise 對象。
30.首屏加載的 js 地址是經過頁面中的 script 標籤來指定的,而間接資源(經過首屏 JS 再進一步加載的 JS)的位置則要經過 output.publicPath 來指定。
31.動態加載的 js 會插入到頁面的 head 標籤,並有一個 async 屬性。
32.在生產環境中咱們關注的是如何讓用戶更快地加載資源,涉及如何壓縮資源、如何添加環境變量優化打包、如何最大限度地利用緩存等。
33.在 DefiinePlugin 中咱們須要在值得外面加上 JSON.stringify。
34.若是對打包速度需求比較高的話,建議使用一個簡化版的 source map。好比,在開發環境中,cheap-module-eval-source-map 一般是一個不錯的選擇,屬於打包速度和源碼信息還原程度的一個良好折中。
35.webpack 提供了 hidden-source-map 及 nosources-source-map 兩種策略來提高 source map 的安全性。前者會產出完整的 map 文件,只不過不會在 bundle 文件中添加對於 map 文件的引用。若是咱們要追溯源碼,則要利用一些第三方服務,將 map 文件上傳到那上面。目前最流行的解決方案是 sentry。後者的安全性沒那麼強,打包以後能在 source 選項卡中看到源碼的目錄結構,可是文件的具體內容會被隱藏起來。
36.對於生產環境的 source map 咱們還有另一種選擇,就是使用 nginx 將 .map 文件只對固定的白名單(好比公司內網)開放。
37.壓縮 js 的工具是 terser,它在 webpack4 裏面是內置模塊,能夠直接使用。它相比 uglifyjs 的有點事支持 es6+ 代碼的壓縮。
38.壓縮 css 文件的前提是使用 exract-text-plugin 或 mini-css-extract-plugin 將樣式提取出來,接着使用 optimize-css-assets-webpack-plugin 來進行壓縮,這個插件本質上使用的是壓縮器 cssnano。
39.資源名的改變也就意味着 html 中的引用路勁的改變。每次更改後都要手動去維護它是很困難的,理想的狀況是在打包結束後自動把最新的資源名同步過去。使用 html-webpack-plugin 能夠幫咱們作到這一點。
40.bundlesize 這個工具包能夠幫助咱們自動化地對資源體積進行監控。
41.開發環境中咱們可能關注的是打包速度,而在生產環境中咱們關注的則是輸出的資源體積以及如何優化客戶端緩存來縮短頁面渲染時間。
42.webpack 是單線程的,假設一個模塊依賴於幾個其它模塊,webpack 必須對這些模塊逐個進行轉譯。雖然這些轉譯任務彼此之間沒有任何依賴關係,卻必須串行地執行。HappyPack 偏偏以此爲切入點,它的核心特性是能夠開啓多個線程,並行地對不一樣模塊進行轉譯,這樣就能夠充分利用本地的計算資源來提高打包速度。
43.從宏觀角度來看,提高性能的方法無非兩種:增長資源或者縮小範圍。增長資源指的是使用更多CPU和內存,用更多的計算能力來縮短執行任務的時間;縮小範圍則是針對任務自己,好比去掉冗餘的流程,儘可能不作重複性的工做等。
44.有些庫咱們是但願 webpack 徹底不要去進行解析的,即不但願應用任何 loader 規則,庫的內部也不會有對其餘模塊的依賴,那麼這時可使用 noParse 對其進行忽略。
45.exclude 和 include 是肯定 loader 的規則範圍,noParse 是不去解析但仍會打包到 bundle 中。最後讓咱們再看一個插件 IgnorePlugin,它能夠徹底排除一些模塊,被排除的模塊即便被引用了也不會被打包進資源文件中。
46.webpack 的 tree shaking 功能能夠在打包過程當中幫助咱們檢測工程中沒有被引用過的模塊,這部分代碼將永遠沒法被執行到,所以也被稱爲「死代碼」。webpack 會對這部分代碼進行標記,並在資源壓縮時將它們從最終的 bundle 中去掉。tree shaking只是爲死代碼添加上標記,真正去除死代碼是經過壓縮工具來進行的。好比說 terser-webpack-plugin(它已經內置在 webpack4 裏面了)
47.即便咱們的項目自己僅僅有一行代碼,webpack 也須要將自身代碼注入進去(大概50行左右)。顯然 rollup 的產出更符合咱們的預期,不包含無關代碼,資源體積更小。
48.在進行技術選型的時候,咱們不只要結合目前工具的一些特性,也要看其將來的發展路線圖。若是其能在後續保持良好的社區生態及維護情況,對於項目從此的發展也是很是有利的。