文章目錄
- webpack做的事情,僅僅是
分析出各種模塊的依賴關係,然後形成資源列表,最終打包生成到指定的文件中
。- webpack也不知道我們需要什麼樣的功能,所以
更多的功能
需要藉助webpack loaders-加載器
和webpack plugins- 插件
完成。loders 和 plugins是webpack的擴展
,webpack只是打包、合併,更過的功能需要用loders 和 plugins去擴展。
1、什麼是 webpack loader-加載器
loader
本質上是一個函數
,它的作用是將某個源碼字符串轉換成另一個源碼字符串返回
。
- loader函數將在模塊解析的過程中被調用,以得到最終的源碼。
loader的出現
npm init -y npm i webpack webpack-cli -D
在
入口文件src/index.js
裏寫如下內容,然後npx webpack
運行,報錯
如下:// var a = 1; 變量 a = 1;
變量 a = 1;
webpack把這句話當作js來解析,不是運行
,是解析,解析時遇到了一些看不懂的東西- webpack中解析模塊的過程中,
抽象語法樹
這一步發生了錯誤,因爲上面的代碼不合法,解析不出來抽象語法樹,所以直接在打包文件中拋出錯誤
- 如果我們就想這樣寫,
在打包時將其視爲正確代碼
,webpack提供了擴展機制,讓用戶可以進行配置 –使用loader
loader本質上就是一個函數
,通常我們把loader寫成一個一個模塊
2、手寫test-loader
這就是一個loader/一個模塊
,它導出一個函數
,這個函數傳入一個參數sourceCode
,然後返回一個字符串
module.exports = function(sourceCode){ //導出一個函數,這個函數傳入一個參數sourceCode --源碼字符串
//sourceCode: 變量 a = 1;
return sourceCode.replace(/變量/g,"var"); //返回一個字符串,使用字符串的replace方法,進行替換 --loader就是這樣,將源碼字符串進行處理返回新的字符串
}
webpack 打包過程中會調用loader這個函數,調用函數的時候,會把源代碼做爲字符串傳進來
,然後函數返回新的代碼格式
,然後webpack拿這個新的代碼格式去做抽象語法樹分析
1、webpack全流程:
根據配置分成很多個chunk
- 每個
chunk根據
一個或者幾個入口模塊
,分析出依賴
的模塊,然後生成資源列表
- 最終按資源列表
打包生成文件
chunk解析出依賴的模塊,形成一個個模塊(模塊列表),然後把這些模塊打包,捆綁到一起,形成一個單獨的js文件 – bundle(捆)
2、chunk中解析模塊的流程(解析模塊的具體流程):
所以loader的位置在 上圖中 讀取文件內容後
,–把文件內容讀出來,然後把文件內容傳遞給loader函數,然後拿loader函數的返回結果,去做抽象語法樹分析
我們按上面的寫法寫好loader
,還需要應用進webpack打包過程中
,否則webpack不知道這是個loader,不知道要去調用loader這個函數,那我們怎麼告訴webpack哪個是需要用到的loader?
3、chunk中解析模塊的更詳細流程
[4-重要]、處理loaders流程:
判斷規則,看模塊是否需要loader來處理
,並不是每個模塊都需要loader來處理,如果不需要則得到一個loaders的空組
,循環的時候,不會做任何處理,就會把源代碼拿去做AST 語法樹分析- 根據
配置的規則
,如果需要loader來處理
,則從規則裏讀取出一個loaders數組
,loaders數組裏,每個loader都是一個函數
- 讀取到loaders數組後,
讓裏面的每一個loader函數去處理
:把文件內容交個數組裏的最後一個loader,然後將loader返回的代碼,交給上一個代碼,直至第一個loader處理後,得到一個最終的代碼,然後進行抽象語法樹分析
3、loader配置:
1、完整配置
module.exports = {
module: { //針對模塊的配置,目前版本只有兩個配置,rules、noParse
rules: [ //模塊匹配規則,可以存在多個規則
{ //每個規則是一個對象
test: /\.js$/, //匹配的模塊正則
use: [ //匹配到後應用的規則模塊
{ //其中一個規則
loader: "模塊路徑", //loader模塊的路徑,該字符串會被放置到require中
options: { //向對應loader傳遞的額外參數
}
}
]
}
]
}
}
-
module:{} 針對模塊的配置
---- 在這個對象
裏配置模塊怎麼去解析,解析時用到哪些loader
,目前只有rules、noParse兩個配置 -
rules:[] 模塊的匹配規則
---- 是一個數組
,webpack根據這裏規則判斷模塊是否需要用到規則中的loaders
module:{
rules:[
{},//規則1,每個規則都是一個對象
{
test:/index\.js$/, //test屬性,屬性值是正則表達式,匹配模塊的路徑
use:[
{},//每個加載器的使用是一個對象
{
loader:'./loaders/test-loader' //加載器的路徑,webpack會自動用require加載 loader加載器裏的內容
options:{ //給loader寫的參數,自定義的內容
changevar:'未知數'
}
}
], //匹配到後,使用哪些加載器,use數組裏是一項項要用到的加載器
}//規則2
], //模塊匹配的規則,從下往上匹配,先看是否需要規則2,然後再看規則1
}
rules數組裏是
一個個規則
,每個規則都是一個對象
,模塊匹配的規則,從下往上匹配
,先看是否需要規則2,然後再看規則1test:正則表達式
– 規則裏的test屬性匹配模塊的路徑
。eg:拿入口文件的路徑./src/index.js
和正則表達式/index\.js$/
匹配上,就要使用對應的loadersuse:[]
use數組裏是一項項用到的加載器`匹配到後,使用哪些加載器,每一項(每個加載器的使用)是一個對象use:[ { loader:'./loaders/test-loader' //加載器的路徑,webpack會自動用require加載 loader加載器裏的內容 },{} ]
noParse
是否不要匹配某個規則
module.exports = {
mode: "development",
module: {
rules: [
{
test: /index\.js$/, //正則表達式,匹配模塊的路徑
use: ["./loaders/loader1", "./loaders/loader2"] //匹配到了之後,使用哪些加載器
}, //規則1
{
test: /\.js$/, //正則表達式,匹配模塊的路徑
use: ["./loaders/loader3", "./loaders/loader4"] //匹配到了之後,使用哪些加載器
} //規則2
], //模塊的匹配規則
}
}
- 上面的代碼中匹配規則得到loaders數組[loader1,loader2,loader3,loaders4],運行處理的時候先loader4 然後依次把結果往前傳
2、簡化配置
module.exports = {
module: { //針對模塊的配置,目前版本只有兩個配置,rules、noParse
rules: [ //模塊匹配規則,可以存在多個規則
{ //每個規則是一個對象
test: /\.js$/, //匹配的模塊正則
use: ["模塊路徑1", "模塊路徑2"]//loader模塊的路徑,該字符串會被放置到require中,如果沒有../則在node_modules裏找,有的話找對應的路徑的模塊
}
]
}
}
3、問題
loader中能不能使用es6 模塊化規範,eg:import ?
不能,loader本質是一個函數,它在webpack打包的過程中被執行,因爲webpack打包是在node環境下運行,所以loader必須是commonjs規範