从 vue-cli 源码中,我发现了27行读取 json 文件有趣的 npm 包
1. 前言
大家好,我是若川。最近組織了源碼共讀活動,感興趣的可以加我微信 ruochuan12 參與,每周大家一起學習200行左右的源碼,共同進步。已進行四個月了,很多小伙伴表示收獲頗豐。
想學源碼,極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。
本文倉庫 https://github.com/lxchuan12/read-pkg-analysis.git,求個star^_^[1]
源碼共讀活動?每周一期,已進行到15期。源碼群里有小伙伴提問,如何用?import?加載?json?文件。同時我之前看到了vue-cli 源碼?里有?read-pkg?這個包。源碼僅27行,非常值得我們學習。
閱讀本文,你將學到:
1.?如何學習調試源碼 2.?學會如何獲取?package.json 3.?學到?import.meta? 4.?學到引入?json?文件的提案 5.?JSON.parse?更友好的錯誤提示 6.?規范化?package?元數據 7.?等等2. 場景
優雅的獲取 package.json 文件。
read-pkg[3]
vue-cli 源碼[4]
const?fs?=?require('fs') const?path?=?require('path') const?readPkg?=?require('read-pkg')exports.resolvePkg?=?function?(context)?{if?(fs.existsSync(path.join(context,?'package.json')))?{return?readPkg.sync({?cwd:?context?})}return?{} }封裝這個函數的commit 記錄[5]
你也許會想直接 require('package.json'); 不就可以了。但在ES模塊下,目前無法直接引入JSON文件。
在 stackoverflow 也有相關提問[6]
我們接著來看 阮一峰老師的 JSON 模塊[7]
import 命令目前只能用于加載 ES 模塊,現在有一個提案[8],允許加載 JSON 模塊。import 命令能夠直接加載 JSON 模塊以后,就可以像下面這樣寫。
import?configData?from?'./config.json'?assert?{?type:?"json"?}; console.log(configData.appName);import 命令導入 JSON 模塊時,命令結尾的 assert {type: "json"} 不可缺 少。這叫做導入斷言,用來告訴 JavaScript 引擎,現在加載的是 JSON 模塊。
接下來我們學習 read-pkg 源碼[9]。
3. 環境準備
3.1 克隆
#?推薦克隆我的項目,保證與文章同步 git?clone?https://github.com/lxchuan12/read-pkg-analysis.git #?npm?i?-g?yarn cd?read-pkg?&&?yarn #?VSCode?直接打開當前項目 #?code?.#?或者克隆官方項目 git?clone?https://github.com/sindresorhus/read-pkg.git #?npm?i?-g?yarn cd?read-pkg?&&?yarn #?VSCode?直接打開當前項目 #?code?.看源碼一般先看 package.json,再看 script。
3.2 package.json
{"name":?"scripts":?{"test":?"xo?&&?ava?&&?tsd"} }test命令有三個包,我們一一查閱了解。
xo[10]
JavaScript/TypeScript linter (ESLint wrapper) with great defaults JavaScript/TypeScript linter(ESLint 包裝器)具有很好的默認值
tsd[11]
Check TypeScript type definitions 檢查 TypeScript 類型定義
nodejs 測試工具 ava[12]
Node.js test runner that lets you develop with confidence
3.3 調試
提前在入口測試文件 test/test.js 和入口文件 index.js 打好斷點。
用最新的VSCode 打開項目,找到 package.json 的 scripts 屬性中的 test 命令。鼠標停留在test命令上,會出現 運行命令 和 調試命令 的選項,選擇 調試命令 即可。
調試如圖所示:
debugger更多調試細節可以看我的這篇文章:新手向:前端程序員必學基本技能——調試JS代碼
我們跟著調試來看測試用例。
4. 測試用例
這個測試用例文件,主要就是主入口 index.js 導出的兩個方法 readPackage, readPackageSync。異步和同步的方法。
判斷讀取的 package.json 的 name 屬性與測試用例的 name 屬性是否相等。
判斷讀取 package.json 的 _id 是否是真值。
同時支持指定目錄。{ cwd }
//?read-pkg/test/test.js import?{fileURLToPath}?from?'url'; import?path?from?'path'; import?test?from?'ava'; import?{readPackage,?readPackageSync}?from?'../index.js';const?dirname?=?path.dirname(fileURLToPath(import.meta.url)); process.chdir(dirname); const?rootCwd?=?path.join(dirname,?'..');test('async',?async?t?=>?{const?package_?=?await?readPackage();t.is(package_.name,?'unicorn');t.truthy(package_._id); });test('async?-?cwd?option',?async?t?=>?{const?package_?=?await?readPackage({cwd:?rootCwd});t.is(package_.name,?'read-pkg'); });test('sync',?t?=>?{const?package_?=?readPackageSync();t.is(package_.name,?'unicorn');t.truthy(package_._id); });test('sync?-?cwd?option',?t?=>?{const?package_?=?readPackageSync({cwd:?rootCwd});t.is(package_.name,?'read-pkg'); });這個測試用例文件,涉及到一些值得一提的知識點。接下來就簡單講述下。
4.1 url 模塊
url 模塊提供用于網址處理和解析的實用工具。
url 中文文檔[13]
url.fileURLToPath(url)
url|要轉換為路徑的文件網址字符串或網址對象。返回:完全解析的特定于平臺的 Node.js 文件路徑。此函數可確保正確解碼百分比編碼字符,并確保跨平臺有效的絕對路徑字符串。
4.2 import.meta.url
import.meta.url[14]
(1)import.meta.url import.meta.url返回當前模塊的 URL 路徑。舉例來說,當前模塊主文件的路徑是https://foo.com/main.js,import.meta.url就返回這個路徑。如果模塊里面還有一個數據文件 data.txt,那么就可以用下面的代碼,獲取這個數據文件的路徑。new URL('data.txt', import.meta.url) 注意,Node.js 環境中,import.meta.url 返回的總是本地路徑,即是file:URL協議的字符串,比如 file:///home/user/foo.js。
4.3 process.chdir
process.chdir() 方法更改 Node.js 進程的當前工作目錄,如果失敗則拋出異常(例如,如果指定的 directory 不存在)。
5. 27行主入口源碼
導出異步和同步的兩個方法,支持傳遞參數對象,cwd 默認是 process.cwd(),normalize 默認標準化。
分別是用 fsPromises.readFile fs.readFileSync 讀取 package.json 文件。
用 parse-json[15] 解析 json 文件。
用 npm 官方庫 normalize-package-data[16] 規范化 package 元數據。
import?process?from?'node:process'; import?fs,?{promises?as?fsPromises}?from?'node:fs'; import?path?from?'node:path'; import?parseJson?from?'parse-json'; import?normalizePackageData?from?'normalize-package-data';export?async?function?readPackage({cwd?=?process.cwd(),?normalize?=?true}?=?{})?{const?filePath?=?path.resolve(cwd,?'package.json');const?json?=?parseJson(await?fsPromises.readFile(filePath,?'utf8'));if?(normalize)?{normalizePackageData(json);}return?json; }export?function?readPackageSync({cwd?=?process.cwd(),?normalize?=?true}?=?{})?{const?filePath?=?path.resolve(cwd,?'package.json');const?json?=?parseJson(fs.readFileSync(filePath,?'utf8'));if?(normalize)?{normalizePackageData(json);}return?json; }5.1 process 進程模塊
很常用的模塊。
process 中文文檔[17]
process 對象提供有關當前 Node.js 進程的信息并對其進行控制。雖然它作為全局可用,但是建議通過 require 或 import 顯式地訪問它:
import?process?from?'node:process';Node 文檔[18]
也就是說引用 node 原生庫可以加 node: 前綴,比如 import util from 'node:util'
5.2 path 路徑模塊
很常用的模塊。
path 中文文檔[19]
path 模塊提供了用于處理文件和目錄的路徑的實用工具。
5.3 fs 文件模塊
很常用的模塊。
fs 中文文檔[20]
5.4 parseJson 解析 JSON
parse-json[21]
文檔介紹:
Parse JSON with more helpful errors
更多有用的錯誤提示。
//?源碼有刪減 const?fallback?=?require('json-parse-even-better-errors'); const?parseJson?=?(string,?reviver,?filename)?=>?{if?(typeof?reviver?===?'string')?{filename?=?reviver;reviver?=?null;}try?{try?{return?JSON.parse(string,?reviver);}?catch?(error)?{fallback(string,?reviver);throw?error;}}?catch?(error)?{//?省略} }5.5 normalizePackageData 規范化包元數據
npm 官方庫 normalize-package-data[22]
normalizes package metadata, typically found in package.json file.
規范化包元數據
module.exports?=?normalize function?normalize?(data,?warn,?strict)?{//?省略若干代碼data._id?=?data.name?+?'@'?+?data.version }這也就是為啥測試用例中用了t.truthy(package_._id); 來檢測 _id 屬性是否為真值。
6. 總結
最后總結下我們學到了如下知識:
1.?如何學習調試源碼 2.?學會如何獲取?package.json 3.?學到?import.meta? 4.?學到引入?json?文件的提案 5.?JSON.parse?更友好的錯誤提示 6.?規范化?package?元數據 7.?等等read-pkg 源碼[23] 整體而言相對比較簡單,但是也有很多可以學習深挖的學習的知識點。
作為一個 npm 包,擁有完善的測試用例。
學 Node.js 可以多找找簡單的 npm 包學習。比直接看官方文檔有趣多了。不懂的就去查官方文檔。查的多了,自然常用的就熟練了。
建議讀者克隆 我的倉庫[24] 動手實踐調試源碼學習。
最后可以持續關注我@若川。歡迎加我微信 ruochuan12 交流,參與 源碼共讀 活動,大家一起學習源碼,共同進步。
參考資料
[1]
本文倉庫 https://github.com/lxchuan12/read-pkg-analysis.git,求個star^_^: https://github.com/lxchuan12/read-pkg-analysis.git
[2]read-pkg: https://npm.im/read-pkg
更多點擊閱讀原文查看
最近組建了一個江西人的前端交流群,如果你是江西人可以加我微信?ruochuan12?私信 江西?拉你進群。
推薦閱讀
整整4個月了,盡全力組織了源碼共讀活動~
我歷時3年才寫了10余篇源碼文章,但收獲了100w+閱讀
老姚淺談:怎么學JavaScript?
我在阿里招前端,該怎么幫你(可進面試群)
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》10余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助1000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
識別上方二維碼加我微信、拉你進源碼共讀群
今日話題
略。分享、收藏、點贊、在看我的文章就是對我最大的支持~
總結
以上是生活随笔為你收集整理的从 vue-cli 源码中,我发现了27行读取 json 文件有趣的 npm 包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [html] 写html代码时,如果缺少
- 下一篇: 工作405-关于vue组件开发过程中一直