![跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/article/000/000/024/634149387b946824.jpg)
每個前端專案都有 npm scripts,我們會用 npm scripts 來組織編譯、包裝、lint 等任務。 【相關教學推薦:nodejs影片教學】
大家可能常常會跑 npm scripts,但卻對這些指令列工具是怎麼實現的並不了解。
那如果想了解這些工具的實作原理,該怎麼做呢?
這就是今天的主題:調試 npm scripts。
這些命令列工具的package.json 裡都會有個bin 字段,來聲明有哪些命令:
![166522276390578跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/671/754/861/166522276390578%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
npm install 這個包以後,就會放到node_modules/.bin 目錄下:
![166522276769042跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/509/257/910/166522276769042%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
這樣我們就可以透過node ./node_modules/.bin/xx 來跑不同的工具了。
我們也可以用 npx 來跑,例如 npx xx,它的作用就是執行 node_modules/.bin 下的本機指令,如果沒有的話會從 npm 下載然後執行。
當然,最常用的還是放到 npm scripts 裡:
![166522277328169跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/726/126/427/166522277328169%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
#這樣就直接 npm run xxx 跑就行了。
npm scripts 本質上還是用 node 來跑這些 script 程式碼,所以調試他們和調試其他 node 程式碼沒啥區別。
也就是可以這樣跑:
在.vscode/launch.json 的偵錯檔案裡,選擇node 的launch program:
![1665222777703000.png 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/550/160/689/1665222777703000.png)
用node 執行node_modules/.bin 下的文件,傳入參數即可:
![166522278149472跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/362/596/409/166522278149472%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
其實還有更簡單的方式,VSCode Debugger 對npm scripts 調試的場景做了封裝,可以直接選擇npm 類型的偵錯配置:
![166522278543091跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/653/293/929/166522278543091%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
#直接指定執行的命令即可:
![166522279023398跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/676/200/823/166522279023398%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
##例如我們就用這個create-react-app 創建的react 專案來嘗試下npm scripts 的調試:
先去node_modules/.bin 下這個文件裡打個斷點:
![166522279577066跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/664/598/168/166522279577066%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
然後點選debug 啟動:
![166522280089363跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/725/783/104/166522280089363%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
你會發現會執行scripts 下的start 模組:
![1665222806897200.png 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/558/417/285/1665222806897200.png)
我們再去start 下打個斷點:
程式碼執行到這裡斷住:
![166522281997458跑 npm scripts,其實有更香的方式 1跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/709/128/702/166522281997458%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
這個config 就是webpack 的設定:
![166522282535284跑 npm scripts,其實有更香的方式 1跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/697/435/483/166522282535284%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
再往下走,會發現啟動了一個server:
![166522283471753跑 npm scripts,其實有更香的方式 1跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/344/428/700/166522283471753%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
我們在server 啟動的回呼函數裡打個斷點,看看瀏覽器是怎麼打開的:
![166522284344019跑 npm scripts,其實有更香的方式 1跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/754/200/793/166522284344019%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
點擊step into 進入這個斷點:
![1665222848787633.gif 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/843/447/714/1665222848787633.gif)
然後單步執行,會走到這樣的程式碼:
依序透過osascript 來啟動這些瀏覽器,啟動失敗的話,try catch 裡直接忽略了:
![1665222854475570.png 1跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/852/311/607/1665222854475570.png)
這些瀏覽器hover 上去就可以看到:
![166522286175992跑 npm scripts,其實有更香的方式 1跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/725/916/197/166522286175992%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
釋放斷點,你會發現瀏覽器開啟了:
![16652228662357跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/336/367/663/16652228662357%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
#這樣,我們不就梳理了一遍react-scripts start 的流程麼?
總結一下就是這樣的:
- 根據輸入的start 指令,執行scripts/start 模組
- 根據配置,建立webpack 的Compiler 物件
- 建立WebpackDevServer
- #server 啟動之後,啟動瀏覽器開啟url
- 開啟url 的實作就是透過osascripts 依序嘗試那些瀏覽器
這樣調試完一遍,我們就對npm run start 有了更深入的認識。
而且,調試的方式跑 script 和直接命令列 npm run start 沒啥區別。
要說區別,唯一的區別可能是這個:
預設偵錯模式下,輸出的內容會在Debug Console 面板顯示:
![1665222874988550.png 1跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/377/815/999/1665222874988550.png)
但這個也可以改:
![166522288185574跑 npm scripts,其實有更香的方式 跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/521/693/933/166522288185574%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
可以切換成integratedTerminal,那就會輸出在terminal 了:
![166522288558207跑 npm scripts,其實有更香的方式 2跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/100/352/837/166522288558207%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
這樣就和平時npm run start 執行沒了任何區別,而且還可以斷點調試,它不香麼?
我們再來看個例子,像是vue cli 所建立的vue 項目,在vue.config.js 裡可以改webpack 配置:
![166522289556744跑 npm scripts,其實有更香的方式 2跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/583/245/216/166522289556744%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
##但如果你想知道預設的配置是啥呢? console.log 麼?
console.log 列印大物件可不是個好主意,它是這樣的:
![166522290011942跑 npm scripts,其實有更香的方式 2跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/618/885/827/166522290011942%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
#有的同學說用JSON.stringify,那個更難看,特別長的一串。
如果你會了調試 npm scripts 呢?
你就可以加一個npm 類型的偵錯配置:
![166522290662843跑 npm scripts,其實有更香的方式 2跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/300/510/539/166522290662843%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
#然後打個斷點,debug 來跑:
![166522291182304跑 npm scripts,其實有更香的方式 2跑 npm scripts,其實有更香的方式](https://img.php.cn/upload/image/319/502/827/166522291182304%E8%B7%91%20npm%20scripts%EF%BC%8C%E5%85%B6%E5%AF%A6%E6%9C%89%E6%9B%B4%E9%A6%99%E7%9A%84%E6%96%B9%E5%BC%8F)
啥配置都能看到,這不香麼?
我舉的例子只是 webpack 的,但其餘的 npm scripts,像是 babel、tsc、eslint、vite 等等都是一樣的除錯方式。
總結
每個專案都有npm scripts,大多數人只是用它們而不會調試它們,所以就算每天用也不知道這些工具的原理。
這些命令列工具都是在 package.json 中聲明一個 bin 字段,然後 install 之後就會放到 node_modules/.bin 下。
可以 node node_modules/.bin/xx 來跑,可以 npx xx 來跑,最常用的還是 npm scripts,透過 npm run xx 來跑。
npm scripts 的調試就是 node 的調試,只不過 VSCode Debugger 做了簡化,可以直接建立 npm 類型的調試配置。
把 console 設定為 integratedTerminal 之後,日誌會輸出到 terminal,和平時直接跑 npm run xx 就沒差別了。而且還可以斷點看看執行邏輯。
跑 npm scripts 之餘,還可以理一下它的實作邏輯,哪裡感興趣斷在哪裡,不比直接跑香麼?
更多node相關知識,請造訪:
nodejs 教學!
以上是跑 npm scripts,其實有更香的方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!