【webpack核心】- 10、loader-1理論 -轉換代碼

  • 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全流程:

在這裏插入圖片描述

  1. 根據配置分成很多個chunk
  2. 每個chunk根據一個或者幾個入口模塊分析出依賴的模塊,然後生成資源列表
  3. 最終按資源列表打包生成文件

chunk解析出依賴的模塊,形成一個個模塊(模塊列表),然後把這些模塊打包,捆綁到一起,形成一個單獨的js文件 – bundle(捆)

2、chunk中解析模塊的流程(解析模塊的具體流程):

在這裏插入圖片描述
所以loader的位置在 上圖中 讀取文件內容後,–把文件內容讀出來,然後把文件內容傳遞給loader函數,然後拿loader函數的返回結果,去做抽象語法樹分析

我們按上面的寫法寫好loader,還需要應用進webpack打包過程中,否則webpack不知道這是個loader,不知道要去調用loader這個函數,那我們怎麼告訴webpack哪個是需要用到的loader?

3、chunk中解析模塊的更詳細流程

在這裏插入圖片描述

[4-重要]、處理loaders流程:

在這裏插入圖片描述

  1. 判斷規則,看模塊是否需要loader來處理,並不是每個模塊都需要loader來處理,如果不需要則得到一個loaders的空組,循環的時候,不會做任何處理,就會把源代碼拿去做AST 語法樹分析
  2. 根據配置的規則,如果需要loader來處理,則從規則裏讀取出一個loaders數組,loaders數組裏,每個loader都是一個函數
  3. 讀取到loaders數組後,讓裏面的每一個loader函數去處理:把文件內容交個數組裏的最後一個loader,然後將loader返回的代碼,交給上一個代碼,直至第一個loader處理後,得到一個最終的代碼,然後進行抽象語法樹分析
    在這裏插入圖片描述

3、loader配置:

1、完整配置

module.exports = {
    module: { //針對模塊的配置,目前版本只有兩個配置,rules、noParse
        rules: [ //模塊匹配規則,可以存在多個規則
            { //每個規則是一個對象
                test: /\.js$/, //匹配的模塊正則
                use: [ //匹配到後應用的規則模塊
                    {  //其中一個規則
                        loader: "模塊路徑", //loader模塊的路徑,該字符串會被放置到require中
                        options: { //向對應loader傳遞的額外參數

                        }
                    }
                ]
            }
        ]
    }
}
  1. module:{} 針對模塊的配置 ---- 在這個對象裏配置模塊怎麼去解析,解析時用到哪些loader,目前只有rules、noParse兩個配置

  2. 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
}
  1. rules數組裏是一個個規則,每個規則都是一個對象模塊匹配的規則,從下往上匹配,先看是否需要規則2,然後再看規則1
  2. test:正則表達式 – 規則裏的test屬性匹配模塊的路徑。eg:拿入口文件的路徑./src/index.js和正則表達式/index\.js$/匹配上,就要使用對應的loaders
  3. use:[] use數組裏是一項項用到的加載器`匹配到後,使用哪些加載器,每一項(每個加載器的使用)是一個對象
  4. use:[ { loader:'./loaders/test-loader' //加載器的路徑,webpack會自動用require加載 loader加載器裏的內容 },{} ]
  5. noParse 是否不要匹配某個規則
module.exports = {
    mode: "development",
    module: {
        rules: [
            {
                test: /index\.js$/, //正則表達式,匹配模塊的路徑
                use: ["./loaders/loader1", "./loaders/loader2"] //匹配到了之後,使用哪些加載器
            }, //規則1
            {
                test: /\.js$/, //正則表達式,匹配模塊的路徑
                use: ["./loaders/loader3", "./loaders/loader4"] //匹配到了之後,使用哪些加載器
            } //規則2
        ], //模塊的匹配規則
    }
}
  1. 上面的代碼中匹配規則得到loaders數組[loader1,loader2,loader3,loaders4],運行處理的時候先loader4 然後依次把結果往前傳
  2. 在這裏插入圖片描述

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規範

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章