[FE] webpack群俠傳(三):log + debug

學(xué)習(xí)源碼的一個(gè)好辦法就是宋彼,跟進(jìn)源碼的邏輯中掂咒,看看流程是怎么樣流轉(zhuǎn)的捅彻,
這需要我們有直接debug代碼的能力逮栅,
有時(shí)候還需要我們?cè)谀承╆P(guān)鍵位置寫入log戚揭。

下面我們從npm run build 命令行工具開始扯饶,想辦法debug進(jìn)webpack中悯姊,
然后在關(guān)鍵位置寫入log。

1. npm scripts

上一篇中揖曾,我們?cè)诿钚兄姓{(diào)用npm run build落萎,
源碼就被自動(dòng)的編譯打包,然后結(jié)果輸出到了 ./dist/index.js 文件中了炭剪。

$ npm run build

> debug-webpack@1.0.0 build ~/Test/debug-webpack
> webpack

Hash: 2e91628041d9a877f709
Version: webpack 4.20.2
Time: 639ms
Built at: 2018-10-09 09:25:24
   Asset       Size  Chunks             Chunk Names
index.js  937 bytes       0  [emitted]  index
Entrypoint index = index.js
[0] ./src/index.js 8 bytes {0} [built]

可是练链,這到底發(fā)生了什么呢?

1.1 npm run build

上一篇中我們?cè)趎pm scripts配置了npm run build命令奴拦,

{
    ...,
    "scripts:": {
        ...,
        "build": "webpack"
    }
    ...,
}

通過(guò)查看npm-run-script文檔兑宇,我們知道,
npm run會(huì)自動(dòng)添加node_module/.bin 到當(dāng)前命令所用的PATH變量中粱坤,
因此隶糕,npm run build 實(shí)際會(huì)調(diào)用 node_modules/.bin/webpack

$ node_modules/.bin/webpack
Hash: 2070b107dceedfc63c72
Version: webpack 4.20.2
Time: 334ms
Built at: 2018-10-09 10:13:05
   Asset       Size  Chunks             Chunk Names
index.js  930 bytes       0  [emitted]  index
Entrypoint index = index.js
[0] ./src/index.js 10 bytes {0} [built]

與執(zhí)行npm run build 效果一樣站玄。

1.2 顯示原身

我在Finder中打開這個(gè)文件看了下枚驻,發(fā)現(xiàn)它是一個(gè)軟鏈接(symbolic link),
于是株旷,我們還要看看它的原身在哪里再登。

$ l ~/.nvm/versions/node/v8.12.0/bin/webpack
lrwxr-xr-x  1 用戶名  staff    41B 10 24 09:50 node_modules/.bin/webpack -> ../_webpack@4.20.2@webpack/bin/webpack.js

我們看到它的原身在這里,

../_webpack@4.20.2@webpack/bin/webpack.js

完整路徑如下晾剖,

~/Test/debug-webpack/node_modules/_webpack@4.20.2@webpack/bin/webpack.js

這就是我們?cè)趎ode_modules中安裝的webpack模塊的文件地址锉矢。

我們來(lái)看看代碼,
https://github.com/webpack/webpack/blob/v4.20.2/bin/webpack.js

#!/usr/bin/env node

process.exitCode = 0;

/**
 * @param {string} command process to run
 * @param {string[]} args commandline arguments
 * @returns {Promise<void>} promise
 */
const runCommand = 
...

以上鏈接是webpack github倉(cāng)庫(kù)的地址齿尽,我已經(jīng)找到了tag為4.20.2的版本位置沽损,
它展示了4.20.2版本的webpack,./bin/webpack.js的源代碼循头。
后文中我們可以使用這樣的方式展示源代碼了绵估。

1.3 Shebang

我們注意到了,./bin/webpack.js 文件頭有一行這樣的代碼卡骂,

#!/usr/bin/env node

它被稱為 Shebang国裳。

在類Unix系統(tǒng)中,包含Shebang的文本全跨,如果作為可執(zhí)行文件調(diào)用缝左,
#!后面指定的解釋器將會(huì)被調(diào)用,用來(lái)執(zhí)行后面的代碼。

Shebang 語(yǔ)法如下渺杉,

#!interpreter [optional-arg]

注:
/usr/bin/env 不是一個(gè)路徑蛇数,而是一個(gè)命令,
后面跟node 參數(shù)少办,就會(huì)找到node并調(diào)用它,
我們來(lái)試試诵原,

$ /usr/bin/env node --version
v8.12.0

2. 寫入日志

上文中英妓,我們了解到,
npm run build最終導(dǎo)致node解釋執(zhí)行了 ./bin/webpack.js 文件绍赛。
由于Node.js是解釋型語(yǔ)言蔓纠,所以,我們可以直接修改源碼吗蚌,來(lái)查看更改效果腿倚。

一般而言,最常見的寫日志的方法是直接使用console.log 蚯妇,
但是我們發(fā)現(xiàn)敷燎,控制臺(tái)還輸出了其他的文本,
我們很難找到自己輸出的信息箩言。

為了展示方便硬贯,我決定使用 debug 模塊來(lái)輸出信息,
它是一個(gè)日志庫(kù)陨收,可以用顏色來(lái)區(qū)分不同的日志饭豹,
看看github倉(cāng)庫(kù)中的官方截圖,

2.1 安裝debug為devDependencies

./bin/webpack.js 位于 ~/Test/debug-webpack/node_modules/_webpack@4.20.2@webpack 文件夾中务漩,
我們進(jìn)入這個(gè)文件夾拄衰,然后安裝debug,

$ cd ~/Test/debug-webpack/node_modules/_webpack@4.20.2@webpack
$ npm i -D debug

2.2 使用debug

在 ./bin/webpack.js 文件頭部調(diào)用debug饵骨,這里我們創(chuàng)建了一個(gè)log變量翘悉。

#!/usr/bin/env node
const log = require('debug')('debug-webpack webpack webpack.js');

...

記得要放到 #!/usr/bin/env node 后面,
其中第二個(gè)參數(shù)debug-webpack webpack webpack.js 稱為namespace 居触,可用于區(qū)分日志的顏色镐确,
這里我們?yōu)檎麄€(gè)文件使用了相同的namespace。

2.3 bin/webpack.js 代碼邏輯

通過(guò)閱讀 ./bin/webpack.js 源碼饼煞,我們發(fā)現(xiàn)源葫,
它首先會(huì)對(duì)已安裝的CLI進(jìn)行檢查,然后會(huì)載入安裝的CLI工具砖瞧。
webpack要求我們必須安裝webpack-cliwebpack-command 之一息堂,否則就會(huì)報(bào)錯(cuò)。

if (installedClis.length === 0) {
    // 報(bào)錯(cuò)
}

源碼位置如下:https://github.com/webpack/webpack/blob/v4.20.2/bin/webpack.js#L84

如果我們已經(jīng)安裝了某一個(gè)CLI的話,就會(huì)加載這個(gè)CLI荣堰,源碼第149-159行床未,

else if (installedClis.length === 1) {
    const path = require("path");
    const pkgPath = require.resolve(`${installedClis[0].package}/package.json`);
    // eslint-disable-next-line node/no-missing-require
    const pkg = require(pkgPath);
    // eslint-disable-next-line node/no-missing-require
    require(path.resolve(
        path.dirname(pkgPath),
        pkg.bin[installedClis[0].binName]
    ));
}

注意以上代碼第7行,webpack動(dòng)態(tài) require了一個(gè)地址振坚,
這時(shí)候我們的log 工具就有用武之地了薇搁。

const cliPath = path.resolve(path.dirname(pkgPath), pkg.bin[installedClis[0].binName]);
log('cliPath: %s', cliPath);
require(cliPath);

2.3 查看日志

直接按原樣調(diào)用npm run build是看不到剛才寫入的日志信息的,
我們還需要傳入前置參數(shù)渡八,

$ DEBUG=debug-webpack* npm run build

The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments, as described > in Shell Parameters. These assignment statements affect only the environment seen by that command.
—— Bash Reference Manual - 3.7.4 Environment

其中名為DEBUG的前置參數(shù)啃洋,是 debug 模塊所需要的,
debug-webpack* 表示我們要輸出所有以debug-webpack 開頭namespace中的日志屎鳍。
我們示例中宏娄,namespacedebug-webpack webpack webpack.js

運(yùn)行結(jié)果如下逮壁,

debug-webpack webpack webpack.js cliPath: ~/Test/debug-webpack/node_modules/_webpack-cli@3.1.2@webpack-cli/bin/cli.js +0ms

3. webpack-cli/bin/cli.js

上文中我們得到了webpack require的CLI地址孵坚,

~/Test/debug-webpack/node_modules/_webpack-cli@3.1.2@webpack-cli/bin/cli.js

源碼位于,https://github.com/webpack/webpack-cli/blob/v3.1.2/bin/cli.js
webpack-cli版本為 v3.1.2窥淆。

分析源碼我們發(fā)現(xiàn)卖宠,代碼中第436行requirewebpack模塊,
https://github.com/webpack/webpack-cli/blob/v3.1.2/bin/cli.js#L436

const webpack = require("webpack");

隨后在第441行忧饭,調(diào)用webpack逗堵,返回了一個(gè)compiler
https://github.com/webpack/webpack-cli/blob/v3.1.2/bin/cli.js#L441

compiler = webpack(options);

最后眷昆,在第533行蜒秤,調(diào)用了compiler.run
https://github.com/webpack/webpack-cli/blob/v3.1.2/bin/cli.js#L533

} else compiler.run(compilerCallback);

4. 開始debug

知道了webpack-cli的代碼邏輯之后亚斋,我們就可以創(chuàng)建一個(gè)debug.js腳本來(lái)模擬webpack-cli調(diào)用了作媚,
在我們上一篇debug-webpack示例項(xiàng)目中,添加一個(gè)./debug.js 文件帅刊,

const webpack = require('webpack');
const options = require('./webpack.config');

const compiler = webpack(options);

compiler.run((...args) => {
    console.log(...args);
});

保持這個(gè)文件打開狀態(tài)纸泡,在以上代碼第6行位置打個(gè)斷點(diǎn),
然后在vscode中按 F5(或者點(diǎn)擊左側(cè)調(diào)試面板赖瞒,再點(diǎn)擊調(diào)試)女揭。


代碼就停在我們的斷點(diǎn)位置上了。

然后我們可以點(diǎn)擊左數(shù)第3個(gè)按鈕栏饮,進(jìn)行單步調(diào)試吧兔,就可以進(jìn)入compiler.run方法中了。


參考

github: debug
github: webpack v4.20.2 ./bin/webpack.js
github: webpack-cli v3.1.2 ./bin/cli.js
Debugging in Visual Studio Code

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末袍嬉,一起剝皮案震驚了整個(gè)濱河市境蔼,隨后出現(xiàn)的幾起案子灶平,更是在濱河造成了極大的恐慌,老刑警劉巖箍土,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逢享,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吴藻,警方通過(guò)查閱死者的電腦和手機(jī)瞒爬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沟堡,“玉大人侧但,你說(shuō)我怎么就攤上這事∠乙叮” “怎么了俊犯?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵妇多,是天一觀的道長(zhǎng)伤哺。 經(jīng)常有香客問我,道長(zhǎng)者祖,這世上最難降的妖魔是什么立莉? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮七问,結(jié)果婚禮上蜓耻,老公的妹妹穿的比我還像新娘。我一直安慰自己械巡,他們只是感情好刹淌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著讥耗,像睡著了一般有勾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上古程,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天蔼卡,我揣著相機(jī)與錄音,去河邊找鬼挣磨。 笑死雇逞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茁裙。 我是一名探鬼主播塘砸,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼晤锥!你這毒婦竟也來(lái)了谣蠢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎眉踱,沒想到半個(gè)月后挤忙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谈喳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年册烈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婿禽。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赏僧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扭倾,到底是詐尸還是另有隱情淀零,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布膛壹,位于F島的核電站驾中,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏模聋。R本人自食惡果不足惜肩民,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望链方。 院中可真熱鬧持痰,春花似錦、人聲如沸祟蚀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)前酿。三九已至患雏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間薪者,已是汗流浹背纵苛。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留言津,地道東北人攻人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像悬槽,于是被迫代替她去往敵國(guó)和親怀吻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容