(本文章還在持續更新中。。。。)
使用webpack做構建也有一段時間了,記錄一下使用webpack的心得。
我們來看看官網對webpack的描述。
webpack is a module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles - often only one - to be loaded by the browser.
It is incredibly configurable, but to get started you only need to understand Four Core Concepts: entry, output, loaders, and plugins.
This document is intended to give a high-level overview of these concepts, while providing links to detailed concept specific use-cases.
簡單來說,webpack是一個現代js應用的模塊管理器。他能正確處理模塊的依賴方式,并且把多個模塊打包成瀏覽器識別的小數量文件(通常來說只有一個文件,但是如果采用異步加載或者代碼拆包的化就有多個了),webpack是基于配置式的,最核心的四個參數是入口、出口、模塊加載器和插件。
入口、出口都好理解,我這里要補充一下output的publicPath參數。默認為/,它是主文件加載其他文件時的路徑前綴。比如你構建時產生了多個js文件,主文件是app.js。app.js加載其他文件時,會在路徑前面補全publicPath。
loaders是用于處理不同的文件。因為webpack是基于nodejs的,而nodejs默認只能識別js文件,所以less、json等文件需要相應的loader來將文件轉換成js。loaders具有如下特點:
- 支持鏈式調用,有先后順序,前一個loader的返回作為下一個loader的輸入
- 最終要生成js
常用的loader總結如下: - file-loader用于生成md5命名的文件
- url-loader 將文章轉換成dataurl的方式
- css-loader加載css文件??梢越馕隼锩娴膇mport,css模塊化。soucemap等
- style-loader將js化的css包裹style標簽,并嵌入到html中,一般配合css-loader使用
-
ts-loader解析typescript
...
plugin
如果說loader是對具體資源類型上對資源文件的轉換擴展。那么plugin則相當于在全局上做擴展。官方推薦plugin插件一覽表
如果有多個chunk共享相同的依賴,我們可以用CommonsChunkPlugin來提取相同的依賴性到當獨的文件
resolve
這個配置很實用。在處理模塊依賴關系的時候,涉及到嵌套比較深的文件,我們很可能會寫出這樣的代碼
import Utility from '../../utilities/utility';
通過resolve.alias就可以設置一個別名,正確的讓webpack從該路徑中查找
alias: {
Utilities: path.resolve(__dirname, 'src/utilities/')
}
通過resolve.modules可以指定node_modules的查找路徑,適用于一個大項目嵌套多個小項目的情況,可以讓小項目共享相同的node_modules,但是如果是同一個包的不同版本,則不可用。
webpack的Code Splitting async
當你的代碼打包后仍很大的時候,你就要考慮進行代碼拆包了。把一些沒有必要立刻加載的代碼拆包,并異步去加載。在webpack中,你可以通過import()和require.ensure來實現
import是es6的一個特性,在webpack中。webpack會把import()命令識別成代碼切割的點(記住,import后面有括號包裹,包裹的為要加載的模塊路徑),而且webpack的import異步加載模塊是基于promise,這意味著低版本瀏覽器你需要加promise的polyfill。
而且import()需要你正確處理依賴項,因為webpack只是單純的將模塊當獨拆包。如果需要處理依賴關系的化,還是使用require.ensure比較合適。
webpck打包項目中包括第三方庫
在webpack打包中,經常會遇到引用第三方庫的情況,這時候你可以將代碼打包成三塊(不包括拆包生成的小chunk)
1.webpack的模塊引入代碼。主要是webpackJsonp的實現和共同的代碼塊。
2.第三方庫
3.主要的業務代碼
要實現上述的三種分離。需要用到CommonsChunkPlugin來分離多次引用的chunk。用DllReferencePlugin和DllPlugin來分離第三方應用。
不過不建議通過這種方式打包第三方依賴庫,還是直接使用第三方庫提供的dist版本吧,直接打包生成的可能是開發中版本而不是release版本。
externals的使用場景
如果在wepack中定義了externals,webpack會在import、require的時候忽略對應模塊,并externals中對應模塊的值賦給模塊。也就是說,該模塊不會被打包進去最終的代碼。比如你externals設置了
并在代碼中對jquery進行了引用
import jquery from "jquery"
webpack在打包的時候會在externals中匹配到jquery,從而只是簡單的進行變量替換
要注意的
webpack使用場景
1.處理代碼依賴。當你項目復雜,需要引入許多靜態資源,而且靜態資源有依賴關系,優先關系時
2.代碼的并包(多個靜態資源合并,在進行模塊化開發一定會用到)
3.代碼的拆包(當你的資源需要多個頁面復用而需要把共同的代碼分離,以便用于瀏覽器緩存時。)
4.代碼構建,需要區分不同的生成環境時。(比如最常見的三層環境。開發環境、測試環境、線上環境。你可以在開發環境搭建hmr來提高編譯效率,在測試環境使用soucemap來方便測試debug,在線上環境壓縮混淆版本管理來減小帶寬消耗和利用緩存)
webpack調用方式
1.通過cli的方式(在終端中使用webpack命令,適合單獨文件需要簡單處理的時候使用)
2.通過nodejs 的api方式 (適合多環境搭建的時候使用,比如區分開發環境、測試環境、線上環境等,如何區別?在cli中不同的命令指向不同的配置文件,不同的配置文件用define-plugin定義環境變量,在代碼中就可以直接使用這個變量了)