大家好,我是若川。最近組織了源碼共讀活動,感興趣的可以加我微信 ruochuan12
本文來自V同學投稿的源碼共讀第六期筆記,寫得很有趣。現在已經進行到第十期了。你或許經常看見 npm 更新的提示
。

面試官可能也會問你,組件庫更新了,怎么讓使用組件的人都知道。本文分析這個提示的原理實現,很有趣。
1前言
Hello,大家好,這里是V同學
今天我們又來看源碼了
今天若川大大沒有寫源碼閱讀的掘金文章
正好,可以讓我們一試身手
考驗一下我們之前跟隨著川大的源碼所鍛煉的源碼閱讀能力
今天我們要看的是 update-notifier 的源碼
老樣子,在我們閱讀源碼之前,先分析一手,看看這個到底是干嘛用的吧
2分析
這個是我們本期源碼閱讀的代碼倉庫
大家可以先克隆下來,我們且慢慢分析
我們可以用5W1H分析法來試著去分析一下
5w1h
那么什么是5w1h呢,簡單來說就是從
原因(Why)
對象(What)
地點(Where)
時間(When)
人員(Who)
方法(How)
這六個緯度去思考
那我們就一個一個來
What
首先,我們要來看看本期源碼是什么
通過度娘,我們可以大致的了解到,我們本期要看的源碼
似乎是一個和更新有關的工具,可以更新你的npm包和cli應用程序

我們在看一下倉庫的readme

現在就非常的清晰明了了,這是一個以非入侵的方式通知你更新的這么一個工具
Why
那么我們為什么要讀它的源碼呢
有一下幾點
1. 美化終端輸出信息,描繪邊框。
2.?我們可以學會怎么去開啟子進程
3.??給一個node方法作為傳參的幾種方式
4.??通過configstore這個庫我們能夠持久化存儲一些信息
5.??通過latest-version獲取對應pkg包的最新版本信息
Who
誰應該去讀他的源碼
以下幾類人適合去讀他的源碼,當然也適合來看看我的源碼閱讀的文章
1.?源碼愛好者
2.?學習愛好者
3.?希望能學到東西的人
4.?V同學的粉絲😜
……
在我的源碼閱讀的文章里面,我會一步一步的手摸手教你怎么去拆分閱讀以及調試源碼
Where
在哪里學的話,這個大家可以視實際情況而定
When
什么時候學的也取決于你的最佳學習時間,每個人的最佳的專注和學習時間不一樣
具體的話視個人情況而定
How
那么我們就到了最關鍵的一點
怎么去讀
沒有讀過源碼的同學請放心
跟著V同學走,手摸手,包你藥到命除🤪
額不不不,是藥到病除
3依賴
剛剛,我們把倉庫的地址克隆下來了,那么接下來我們就安裝一下依賴吧
進入到對應的倉庫地址
輸入一下命令
npm?i?或者yarn
4測試
測試非常的重要,他可以讓我們非常清晰的了解
一個框架的功能以及作者寫這個測試的意圖,所以我們看源碼,可以先看看測試
我這邊用的是 vscode
找到 package.json 文件,點擊調試
進入測試
有人說了,我用的不是vscode怎么辦呢
其實也簡單的
首先還是先問問百度,你是用的編譯器是否有對應的測試插件
沒有的話,可以在編譯器的控制臺輸入測試中的命令
npm?run?test或者yarn?test
即可運行對應的測試,這個是看全部代碼的方式
具體通過測試看源碼的案例,可以看我的這一篇筆記
5準備
今天我們只看核心代碼
所以我們進入example 這個 JS 文件里面去
這個案例非常的簡單,一共就17行代碼

運行第四行作者給我們的命令
node?example
我們發現沒有反應,那么這是怎么一回事呢
我們來看一下注釋
You?have?to?run?this?file?two?times?the?first?time
翻譯過來就是第一次必須運行此文件兩次
嘿,我運行過的別的程序都只需要運行一次,就你要運行兩次,你搞特殊是嗎😶?
那么我們仔細來想想,要運行兩次呢?
我們在來看看注釋
This?is?because?it?never?reports?updates?on?the?first?run
翻譯過來就是
這是因為它不會在第一次運行時報告更新
我們帶著第一次為什么不會更新的問題來看源碼
對于vscode進行node調試
我把過程放在以下gif圖里面,大家可以進行參考

6閱讀
首先我們在example里面打上斷點

然后進入調試
我們這時候發現,斷點進來了

我們點擊調試的↓按鈕
我們發現我們進到了index.js文件里面
所以這個就是他的核心文件

我們進入到了183行
第一部分:實例化對象
在往下走,我們進入到了第一部分

我們傳入的參數會被option接到
然后對拿到的對象進行數據清洗,只保留需要的數據
如果沒有需要的數據,就給他拋出個錯誤

接下來把需要的數據掛載到實例對象身上
檢查更新時間是否符合規范
知識點:process.env 是 Node.js 中的一個環境對象。其中保存著系統的環境的變量信息。
通過獲取process檢查是否禁用更新
知識點:isCi的作用是如果當前環境是持續集成服務器,則返回true
判斷是否在Npm腳本中通知

判斷一下你是否禁用更新了
知識點:ConfigStore的作用是輕松加載和保留配置,而無需考慮在哪里以及如何
知識點:Chalk的作用是讓你的終端更美觀好看,具體在Vue-release這篇文章中有提到過
如果你沒禁用的話,幫你把包名通過ConfigStore
進行持久化存儲,順便把最后一次檢查的時間更新成現在
第二部分:檢查更新
接下來我們順著代碼的路徑,走到了中間這一行

進去的第一目光我們的卡姿蘭大眼睛就可以看到好幾個判斷


第一個判斷的大概意思是
如果你沒有本地存儲或者禁用更新的情況下,那么就不執行了,我們就說拜拜了
接下來,他拿到我們的之前存進去的update對象來更新
關鍵點
這里有一個關鍵點,就是我們之前埋下的坑
他第一次為什么不執行
因為這里第一次的時候,我們沒有執行過check.js這個文件
所以我們這里的這個update是空的
這里在埋下一個點,為什么updata是空的導致他只執行一次呢,這個后文會講到
我們接著往下看

知識點:spawn => 詳情請參考spawn
這里通過spawn
開啟一個子進程,運行check.js
,然后把options
作為調用check.js
的命令行參數
check.js文件
接下來我們就進入到了check.js文件里面

const?options?=?JSON.parse(process.argv[2]);
這一段代碼,意思是把我們剛才通過控制臺傳的option參數拿過來
知識點:latestVersion => 獲取最新版本的 npm 包
拿過來之后新建一個實例 ,然后去拿到對應的包名、最新版本、當前版本、版本差別的信息
拿到信息之后,更新一下最后一次檢查更新對應的時間
在順便把信息塞到持久化存儲當中的update里面、
然后關閉spawn
打開的子進程,返回原來的函數里面
第三部分
當拿到最新版本的信息之后,他會把對應的實例對象返回出去
返回到了example.js文件里面
返回到了example之后去執行notify

雖然說,之前的update被存進去了,但是在notify的時候沒有被讀出來
所以就導致之前的update因為是空的,在最開始的時候,進不去notify的函數,就被return掉了
這就是為什么第一次執行的時候,什么都不返回的原因了
知識點:is-installed-globally:檢查您的軟件包是否已全局安裝
知識點:is-yarn-global:檢查您的yarn包是否已全局安裝
接下來他會檢查你是不是全局安裝了,全局是不是用的yarn安裝的
接下來就是控制你的控制臺,在你的控制臺上輸入一些安裝命令
知識點:boxen:在終端中創建框
完成之后,通過boxen構建一個框框,然后用template去顯示更新信息
7總結
我們用了5w1h分析法,在看源碼之前進行了分析思考
我們學會了怎么去通過編譯器,去調試測試用例
我們知道了看源碼前應該做哪些準備
我們知道了可以帶著問題去看源碼,可以提高你的閱讀效率
我們知道了檢查更新npm文件的全部流程
我們知道了process.env 是 Node.js 中的一個環境對象,里面保存著系統的環境的變量信息
ConfigStore可以進行持久化存儲
Chalk可以讓你的終端更好看
spawn可以生成一個子進程去執行命令
is-installed-globally可以檢查你的軟件包是否已全局安裝
is-yarn-global可以檢查你全局安裝的是否是通過yarn安裝的
在終端中畫框框可以用 boxen
isCi的作用可以判斷當前環境是持續集成服務器
latestVersion可以獲取最新版本的 npm 包
最主要的是,我們學會了怎么樣去從一個啥也不是的小白,去學習,去拆分源碼,解構源碼,理解作者的思路與想法,我們可以把步子邁的小一點,一小步一小步的去走,步子太大了容易摔倒,把它掰開了揉碎了,慢慢消化吸收理解,成為自己的東西!加油,奧利給!
最近組建了一個江西人的前端交流群,如果你是江西人可以加我微信?ruochuan12?私信 江西?拉你進群。
推薦閱讀
1個月,200+人,一起讀了4周源碼
我歷時3年才寫了10余篇源碼文章,但收獲了100w+閱讀
老姚淺談:怎么學JavaScript?
我在阿里招前端,該怎么幫你(可進面試群)
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動
識別上方二維碼加我微信、拉你進源碼共讀群
今日話題
略。歡迎分享、收藏、點贊、在看我的公眾號文章~