之前在開發(fā)過程中一雖然了解過一些webpcak的基礎(chǔ)知識鞋诗,但是對webpack的流程還是知道的太少而涉,所以這次學(xué)習(xí)了下webpack中l(wèi)oader的知識。
webpack 工作流程
關(guān)于 webpack 的工作流程速那,簡單來說可以概括為以下幾步:
1劳淆、參數(shù)解析
2凉翻、找到入口文件
3兰伤、調(diào)用 Loader 編譯文件
4内颗、遍歷 AST,收集依賴
5医清、生成 Chunk
6起暮、輸出文件
關(guān)于 Loader
Loader 的作用很簡單,就是處理任意類型的文件会烙,并且將它們轉(zhuǎn)換成一個(gè)讓 webpack 可以處理的有效模塊。
- Loader 的配置和使用
1.1 在 config 里配置
Loader 可以在 webpack.config.js里配置筒捺,這也是推薦的做法柏腻,定義在 module.rules 里:
// webpack.config.js
module.exports = {
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader' },
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'postcss-loader' },
]
}
]
}
};
每一條 rule 會(huì)包含兩個(gè)屬性:test 和 use,比如 { test: /.js$/, use: 'babel-loader' } 意思就是:當(dāng) webpack 遇到擴(kuò)展名為 js 的文件時(shí)系吭,先用 babel-loader 處理一下五嫂,然后再打包它。
use 的類型:string|array|object|function:
string: 只有一個(gè) Loader 時(shí)肯尺,直接聲明 Loader沃缘,比如 babel-loader。
array: 聲明多個(gè) Loader 時(shí)则吟,使用數(shù)組形式聲明槐臀,比如上文聲明 .css 的 Loader。
object: 只有一個(gè) Loader 時(shí)氓仲,需要有額外的配置項(xiàng)時(shí)水慨。
function: use 也支持回調(diào)函數(shù)的形式。
注意: 當(dāng) use 是通過數(shù)組形式聲明 Loader 時(shí)敬扛,Loader 的執(zhí)行順序是從右到左晰洒,從下到上。比如暫且認(rèn)為上方聲明是這樣執(zhí)行的:
postcss-loader -> css-loader -> style-loader
其實(shí)就是:
styleLoader(cssLoader(postcssLoader(content)))
1.2 內(nèi)聯(lián)
可以在 import 等語句里指定 Loader啥箭,使用 ! 來將 Loader分開:
import style from 'style-loader!css-loader?modules!./styles.css';
內(nèi)聯(lián)時(shí)谍珊,通過 query 來傳遞參數(shù),例如 ?key=value急侥。
一般來說砌滞,推薦使用統(tǒng)一 config 的形式來配置 Loader炼七,內(nèi)聯(lián)形式多出現(xiàn)于 Loader 內(nèi)部,比如 style-loader 會(huì)在自身代碼里引入 css-loader:
require("!!../../node_modules/css-loader/dist/cjs.js!./styles.css");
- Loader 類型
2.1 同步 Loader
module.exports = function(source) {
const result = someSyncOperation(source); // 同步邏輯
return result;
}
一般來說布持,Loader 都是同步的豌拙,通過 return 或者 this.callback 來同步地返回 source轉(zhuǎn)換后的結(jié)果。
2.2 異步 Loader
在 Loader 里做一些異步的事情题暖,比如說需要發(fā)送網(wǎng)絡(luò)請求按傅。如果同步地等著,網(wǎng)絡(luò)請求就會(huì)阻塞整個(gè)構(gòu)建過程胧卤,這個(gè)時(shí)候我們就需要進(jìn)行異步 Loader唯绍,可以這樣做:
module.exports = function(source) {
// 告訴 webpack 這次轉(zhuǎn)換是異步的
const callback = this.async();
// 異步邏輯
someAsyncOperation(content, function(err, result) {
if (err) return callback(err);
// 通過 callback 來返回異步處理的結(jié)果
callback(null, result, map, meta);
});
};
2.3 Pitching Loader
{
test: /\.js$/,
use: [
{ loader: 'aa-loader' },
{ loader: 'bb-loader' },
{ loader: 'cc-loader' },
]
}
Loader 總是從右到左被調(diào)用。上面配置的 Loader枝誊,就會(huì)按照以下順序執(zhí)行:
cc-loader -> bb-loader -> aa-loader
每個(gè) Loader 都支持一個(gè) pitch 屬性况芒,通過 module.exports.pitch 聲明。如果該 Loader 聲明了 pitch叶撒,則該方法會(huì)優(yōu)先于 Loader 的實(shí)際方法先執(zhí)行绝骚,官方也給出了執(zhí)行順序:
|- aa-loader `pitch`
|- bb-loader `pitch`
|- cc-loader `pitch`
|- requested module is picked up as a dependency
|- cc-loader normal execution
|- bb-loader normal execution
|- aa-loader normal execution
也就是會(huì)先從左向右執(zhí)行一次每個(gè) Loader 的 pitch 方法,再按照從右向左的順序執(zhí)行其實(shí)際方法祠够。
Loader 工作流程簡述
我們來回顧一下 Loader 的一些特點(diǎn):
Loader 是一個(gè) node 模塊压汪;
Loader 可以處理任意類型的文件,轉(zhuǎn)換成 webpack 可以處理的模塊古瓤;
Loader 可以在 webpack.config.js 里配置止剖,也可以在 require 語句里內(nèi)聯(lián);
Loader 可以根據(jù)配置從右向左鏈?zhǔn)綀?zhí)行落君;
Loader 接受源文件內(nèi)容字符串或者 Buffer穿香;
Loader 分為多種類型:同步、異步和 pitching绎速,他們的執(zhí)行流程不一樣皮获;
webpack 為 Loader 提供了一個(gè)上下文,有一些 api 可以使用朝氓;
我們根據(jù)以上暫時(shí)知道的特點(diǎn)魔市,可以對 Loader 的工作流程有個(gè)猜測,假設(shè)有一個(gè) js-loader赵哲,它的工作流程簡單來說是這樣的:
- webpack.config.js 里配置了一個(gè) js 的 Loader待德;
- 遇到 js 文件時(shí),觸發(fā)了 js-loader;
- js-loader 接受了一個(gè)表示該 js 文件內(nèi)容的 source;
- js-loader 使用 webapck 提供的一系列 api 對 source 進(jìn)行轉(zhuǎn)換枫夺,得到一個(gè) result;
- 將 result 返回或者傳遞給下一個(gè) Loader将宪,直到處理完畢。
未完待續(xù)。较坛。印蔗。