EP5 - 作為一個前端工程師,我是怎麼debug的

這集講講工程師的必備技能之一

debugging

這也不局限於前端工程師 只要是工程師在任何職涯階段一定都會碰到有bug需要debug的時候

不一定是你寫的可能是別人寫的code需要debug

我覺得這個機會是增長自己能力最快的方法而且也會慢慢累積一套自己的best practices和anti-pattern

會記得之前這樣寫產生了什麼樣的問題所以下次要注意

我之前遇到過一個bug是不曉得為什麼使用者沒法等入了

後來發現是我們GraphQL那邊中間因為要有logging的需求但不想直接顯示使用者打的密碼所以會變成星號

但不小心的是因為JavaScript object是pass by reference的 我們直接改了那個object

導致某些操作下使用者的密碼真的變成星號了

是一個寶貴的經驗哈哈

我覺得debug的第一步要先承認你所覺得的這段code應該怎麼操作的可能是不對的

要是對的它就不會這樣了

情緒要先放下來 看過很多人對著電腦喃喃自語說why doesn't it work???

bug不是我們說一說它自己就會好了

如果可以的話請教教我

alright 假設今天有使用者回報說這個頁面有bug 我們先試著reproduce試試按照使用者說的什麼先點了這個畫面 打了什麼字 按了什麼的button結果應該跳出個modal但沒有

根據bug的輕重緩急我們不一定會馬上修, bug ticket如果是我們工程師開那記得一定要把reproduce steps寫上去好讓下一個拿到這ticket的人可以試著修看看

不要一張ticket說 使用者說這個modal沒有跳出來

萬一是個剛進來的新人對business還不了解 拿到這個ticket他會有很多問號

有時候使用者不會特別跟我們說有bug除非你在大公司上班然後instagram上不去 或是 AWS server is down 那你馬上在新聞上面看到然後twitter上面刷一排為何上不去 then you know you are messed up

台灣我不是很清楚但北美這邊都會在application裡面 不管是前端還是後端 都會放比如Sentry 或是 DataDog這類monitoring tool 會把application報的錯全部放到平台上而我們工程師可以隨時查看 你也可以設定說某個error在過去一分鐘內發生3次就自動發到Slack上因為代表這類error很重要

不管使用者有沒有和你說 我們都得看懂stack trace

stack trace通常是一個error object帶上的很多相關訊息比如這個error怎麼被throw出來的 被誰throw出來的 在哪一行被throw 我們常常會這個function call那個function又call另一個function stack trace會把這些過去的路徑全部顯示出來 尤其前端我們會有build bundle 如果有source map這些monitoring platform會自動幫你把error link回source code 而不是這個a和b報錯 誰知道a跟b是什麼東西

剛剛提到的source map它的定義是a file that maps the transformed source to the original source

webpack和vite都能選擇性的build時候產生出這個檔案

我們build的時候這些code通常都是minified的 變成人很難看得懂東西

有了這個檔案這些工具和browser就能自動串起來把我們build好的code和原始碼串起來讓你在不deploy source code情況下還可以看到source code

通常建議不要在production把source map deploy出去畢竟這樣大家都能看到原始碼

第二個這個聽起來好像理所當然但情急之下加上網站有時候長得一樣自己會沒有發現

別在production上debug然後確定東西沒有被cache

在reproduce過程中可能需要update什麼data或是比如是個e-commerce你需要真的走過checkout flow

記得在dev environment做這些事

有些bug但其實不是bug是說這東西怎麼沒有跑出來 可能只是目前cache的是舊的東西 等cache invalidate之後就好了 我們也就不用再花時間看了

第三點是善用與熟悉devtool 瀏覽器在使用者手上只是個用來上網的工具各個瀏覽器中有很多好用的開發者工具

最基本的可以看到console有跳出什麼錯誤訊息

network看這個網頁從server拿到什麼資料

local storage 可以看這個app存了什麼data

給個example 假設這個頁面我們應該看到某種資料但畫面顯示說no data found

最初步的判斷可以先從network查那個有沒有這個request 或 response是不是有資料回來

如果沒有request或是response有資料結果畫面沒東西那大概就是前端有問題 如果response回來本來就沒有資料然後也是照著API doc發request的那就要請後端同事一起debug了

第四點 善用console 相關的method

大家最常用的大概就是console.log 在你的console print出任何data或string

最簡單的例子比如你要測你這個function有拿到你覺得應該有的資料

就直接用console.log來看拿到了什麼資料

或是在一連串的function裡面想知道這些function有沒有被call

用console.log來測試會不會print

console.time可以讓你簡單的測試function花多久時間跑完

第五點是可以用breakpoint和step over function

你可以在devtool裡面 以chrome為例有個sources tab 在code的某一行打上breakpoint

當browser跑到那一行時候 根據設定的condition browser會停在那邊

如果預期會停在這邊結果怎麼跑都沒有那maybe哪裡的condition設定錯了

多加一點breakpoint或是console log看看

那如果停住了 可以看看code跑到這邊 其他的variable裡面的value是什麼

幫助判斷code跑到這邊 該拿資料有沒有拿到

devtool也會給stack trace告訴你是誰叫了這一個function然後誰叫了那一個

整個history都會被列出來

然後你可以控制browser跑下一行或是跳出這個function

這可以讓你更準確的知道瀏覽器是怎麼執行你的code他的順序如何

這個如果是在local弄或是有source map的狀況下弄會比較簡單

要不然你會看這minified code猜為什麼這個f要叫這個h 這兩個是什麼鬼

第六點算life hack吧

就先去做別的事情 休息一下

應該蠻多人是在洗澡時候或睡一覺醒來後把一個bug解決了

只能說腦袋是個很神奇的東西

第七點 試著讀別人的code 尤其是library的code

今天你覺得 你篤定 是某個library有bug所以有一些奇怪的behavior

你不妨試試用前面的方法 或是node_modules 裡面打console.log 或是去他們的github抓source code下來讀

說不定還能順便發個PR直接修bug 在resume上面寫對open source用貢獻

第八點我發現蠻多人用但很少人有寫出來

大概概念是用binary search

不是要你寫出來

是當你完全不曉得為何目前這個bug會是這個樣子

你就開始刪code

但一個一個刪太慢了 你就一次刪一半

如果bug還在 再刪剩下一半

如果發現bug沒了

把刪掉的一半加回一半

那如果整個檔案都刪掉了bug還在

那就是不在這個檔案裡

找下一個開刀

這雖然不是特別的scientific但很有效

當初Vue 3剛出來時候我們的SSR要migrate到Vue 3

當時有一個bug是在某一個點Vue會沒辦法繼續render然後server crash

就是用這個方法找到哪一行然後回報給Vue team的

如果你喜歡這內容的話幫我在 Twitter 和 Threads 上面分享給其他正在前端這條路上努力的朋友們,也別忘了訂閱我們電子報收到第一手消息喔 🚀