看了就会的 Node.js 三大基础模块常用 API
大家好,我是若川。歡迎加我微信?ruochuan12,加群交流學(xué)習(xí)。今天分享一篇nodejs基礎(chǔ)的文章。點(diǎn)擊下方卡片關(guān)注我,或者查看源碼等系列文章。
在日常使用 Node 進(jìn)行開發(fā)的時(shí)候,會(huì)使用到一些文件系統(tǒng)、路徑操作等基礎(chǔ) API,這里整理一下,方便大家理解和直接使用。
這里只介紹最常用的那些,不是所有哈,想要看更全的,直接看官方文檔[1]就 OK。
盡量不廢話,多上代碼。
Process 模塊
先介紹 process 模塊,它提供了當(dāng)前 Node 進(jìn)程相關(guān)的全局環(huán)境信息。在后面的 API 中被用到。
//?內(nèi)置模塊,直接使用 const?process?=?require('process');process.cwd()
這是一個(gè)函數(shù),返回當(dāng)前 Node 進(jìn)程執(zhí)行的目錄,舉例一個(gè)常見的場景:
一個(gè) Node 模塊 A 通過 NPM 發(fā)布,項(xiàng)目 B 中使用了模塊 A。在 A 中需要操作 B 項(xiàng)目下的文件時(shí),就可以用 process.cwd() 來獲取 B 項(xiàng)目的路徑。
const?cwd?=?process.cwd();?//?輸出:/Users/xiaolian/Code/node-api-testprocess.argv
在終端通過 Node 執(zhí)行命令的時(shí)候,通過 process.argv 可以獲取傳入的命令行參數(shù),返回值是一個(gè)數(shù)組:
0: Node 路徑(一般用不到,直接忽略)
1: 被執(zhí)行的 JS 文件路徑(一般用不到,直接忽略)
2~n: 真實(shí)傳入命令的參數(shù)**
所以,我們只要從 process.argv[2] 開始獲取就好了。一般都是這樣用:
const?args?=?process.argv.slice(2);直接獲取我們想要的參數(shù)。
process.env
返回一個(gè)對象,存儲(chǔ)當(dāng)前環(huán)境相關(guān)的所有信息,一般很少直接用到。
一般我們會(huì)在 process.env 上掛載一些變量標(biāo)識(shí)當(dāng)前的環(huán)境。比如最常見的用 process.env.NODE_ENV 區(qū)分 development 和 production。在 vue-cli 的源碼中也經(jīng)常會(huì)看到 process.env.VUE_CLI_DEBUG 標(biāo)識(shí)當(dāng)前是不是一 DEBUG 模式。
這里提一個(gè) webpack 的插件 DefinePlugin[2],在日常的構(gòu)建流程中,我們經(jīng)常會(huì)通過這個(gè)插件來注入不同的全局變量,從而執(zhí)行不同的構(gòu)建流程,并且代碼中的 process.env.xxx 會(huì)被替換成具體的值,在 Terser 壓縮階段會(huì)將 deadCode 移除,優(yōu)化代碼體積。
process.platform
這個(gè)用的不多,返回當(dāng)前系統(tǒng)信息,枚舉值如下:
console.log(process.platform);//?'aix' //?'darwin'??-?macOS //?'freebsd' //?'linux'?-?linux //?'openbsd' //?'sunos' //?'win32'?-?windowsPath 模塊
//?內(nèi)置模塊,直接使用 const?path?=?require('path');Node 中幾乎路徑相關(guān)的操作都會(huì)使用這個(gè)模塊。
這里就說 5 個(gè)最常用的:
path.join(...paths)
path.join 作用是將傳入的多個(gè)路徑拼成一個(gè)完整的路徑。
const?dPath?=?path.join('template',?'aaa',?'bbb',?'ccc',?'d.js'); //?輸出:?template/aaa/bbb/ccc/d.js來看一個(gè)非常常見的場景,我們需要獲取當(dāng)前項(xiàng)目的 package.json 文件,就可以這樣獲取它的路徑:
const?pkgPath?=?path.join(process.cwd(),?'./package.json'); //?輸出:?/Users/xiaolian/Code/node-api-test/package.jsonpath.join 可以傳入任意個(gè)路徑,比如:
['package.json',?'README.md'].forEach(fileName?=>?{const?templateFilePath?=?path.join(process.cwd(),?'template',?fileName);console.log(templateFilePath); }); //?輸出:?/Users/xiaolian/Code/node-api-test/template/package.json //?輸出:?/Users/xiaolian/Code/node-api-test/template/README.mdpath.resolve(...paths)
path.resovle 和 path.join 的區(qū)別在于它的作用是將傳入的多個(gè)路徑和當(dāng)前執(zhí)行路徑拼接成一個(gè)完整的絕對路徑。
假設(shè)我現(xiàn)在 index.js 在 scripts 目錄下,然后我在根目錄下執(zhí)行 node scripts/index.js,它的代碼如下:
const?dPath?=?path.resolve('aaa',?'bbb',?'ccc',?'d.js'); //?輸出:??/Users/xiaolian/Code/node-api-test/aaa/bbb/ccc/d.js一般情況下,當(dāng) path.resolve 的第一個(gè)參數(shù)為 ./ 時(shí),可以直接理解和 path.join(processs.cwd(), '') 表現(xiàn)一致。
path.basename(path[, ext])
path.basename 返回指定 path 最后一個(gè)路徑名,其中第二個(gè)參數(shù) ext 可選,表示文件擴(kuò)展名。比如:
console.log(path.basename('scripts/index.js'));??//?index.js console.log(path.basename('scripts/index.js',?'.js'));??//?匹配到?.js,返回?index console.log(path.basename('scripts/index.js',?'.json'));??//?沒匹配到,返回?index.jspath.dirname(path)
和 path.basename 對應(yīng),返回指定 path 最后一個(gè)路徑名之前的路徑。比如:
console.log(path.basename('scripts/index.js'));??//?scripts console.log(path.basename('scripts/hook/index.js'));??//?scripts/hookpath.extname(path)
和 path.basename 對應(yīng),返回指定 path 最后一個(gè)路徑名的文件擴(kuò)展名(含小數(shù)點(diǎn) .)。比如:
console.log(path.basename('scripts/index.js'));??//?.js console.log(path.basename('README.md'));??//?.md對比
最后再來對比一下各個(gè)路徑相關(guān)的 API 的區(qū)別。
項(xiàng)目 A 的目錄結(jié)構(gòu)如下:
├──?scripts │???└──?index.js ├──?src │???└──?index.js ├──?package.json ├──?README.mdscripts/index.js 的代碼如下:
const?path?=?require('path');console.log(path.join('package.json')); console.log(path.resolve('package.json')); console.log(path.join('src',?'index.js')); console.log(path.resolve('src',?'index.js')); console.log(path.join(process.cwd(),?'package.json')); console.log(path.resolve('./',?'package.json')); console.log(__filename); console.log(__dirname);然后,我們在項(xiàng)目 A 的根目錄下執(zhí)行 node scripts/index.js,結(jié)果如下:
->?node?scripts/index.js package.json /Users/xiaolian/Code/A/package.json src/index.js /Users/xiaolian/Code/A/src/index.js /Users/xiaolian/Code/A/package.json /Users/xiaolian/Code/A/package.json /Users/xiaolian/Code/A/scripts/index.js /Users/xiaolian/Code/A/scripts品,仔細(xì)品,它們有什么區(qū)別。
個(gè)人而言,一般還是習(xí)慣用 path.join(process.cwd(), 'xxx')。
File System 模塊
//?內(nèi)置模塊,直接使用 const?fs?=?require('fs');文件系統(tǒng)相關(guān)操作的模塊,除了 fs 之外,我們還經(jīng)常用到 fs-extra,后面會(huì)介紹。
這個(gè)模塊在平時(shí)的 Node 開發(fā)中會(huì)被大量使用,這里簡單列幾個(gè),其它的還是看文檔哈:https://nodejs.org/dist/latest-v14.x/docs/api/fs.html[3]
fs 模塊的 API 默認(rèn)都是異步回調(diào)的形式,如果你想使用同步的方法,有兩種解決方法:
使用 Node 提供的同步 API:xxxSync,也就是在 API 的后面加一個(gè) Sync 后綴,它就是一個(gè)同步方法了(具體還是需要查文檔哈,是否有提供同步 API)
包裝成一個(gè) Promise 使用
fs.stat(path[, options], callback)
fs.stat() 返回一個(gè)文件或者目錄的信息。
const?fs?=?require('fs');fs.stat('a.js',?function(err,?stats)?{console.log(stats); });其中包含的參數(shù)有很多,介紹幾個(gè)比較常用的:
export?interface?StatsBase<T>?{isFile():?boolean;?????????????????//?判斷是否是一個(gè)文件isDirectory():?boolean;????????????//?判斷是否一個(gè)目錄size:?T;???????????????????????????//?大小(字節(jié)數(shù))atime:?Date;???????????????????????//?訪問時(shí)間mtime:?Date;???????????????????????//?上次文件內(nèi)容修改時(shí)間ctime:?Date;???????????????????????//?上次文件狀態(tài)改變時(shí)間birthtime:?Date;???????????????????//?創(chuàng)建時(shí)間 }一般我們會(huì)使用 fs.stat 來取文件的大小,做一些判斷邏輯,比如發(fā)布的時(shí)候可以檢測文件大小是否符合規(guī)范。在 CLI 中,經(jīng)常需要獲取一個(gè)路徑下的所有文件,這時(shí)候也需要使用 fs.stat 來判斷是目錄還是文件,如果是目錄則繼續(xù)遞歸。當(dāng)然,現(xiàn)在也有更方便的 API 可以完成這個(gè)工作。
同步方法
const?fs?=?require('fs');try?{const?stats?=?fs.statSync('a.js'); }?catch(e)?{}fs.readdir(path[, options], callback)
fs.readdir(path) 獲取 path 目錄下的文件和目錄,返回值為一個(gè)包含 file 和 directory 的數(shù)組。
假設(shè)當(dāng)前目錄為:
. ├──?a │???├──?a.js │???└──?b │???????└──?b.js ├──?index.js └──?package.json執(zhí)行以下代碼:
const?fs?=?require('fs');fs.readdir(process.cwd(),?function?(error,?files)?{if?(!error)?{console.log(files);} });返回值為:
[?'a','index.js','package.json'?]可以看到這里只返回了根目錄下的文件和目錄,并沒有去深度遍歷。所以如果需要獲取所有文件名,就需要自己實(shí)現(xiàn)遞歸。
同步方法
const?fs?=?require('fs');try?{const?dirs?=?fs.readdirSync(process.cwd()); }?catch(e)?{}fs.readFile(path[, options], callback)
文件讀取的 API,通過 fs.readFile 可以獲取指定 path 的文件內(nèi)容。
入?yún)⑷缦?#xff1a;
第一個(gè)參數(shù): 文件路徑
第二個(gè)參數(shù): 配置對象,包括 encoding 和 flag,也可以直接傳如 encoding 字符串
第三個(gè)參數(shù): 回調(diào)函數(shù)
使用方法如下:
const?fs?=?require('fs'); const?path?=?require('path');fs.readFile(path.join(process.cwd(),?'package.json'),?'utf-8',?function?(error,content )?{if?(!error)?{console.log(content);} });如果沒傳 encoding,則其默認(rèn)值為 null,此時(shí)返回的文件內(nèi)容為 Buffer 格式。
同步方法
const?fs?=?require('fs');try?{fs.readFileSync(path.join(process.cwd(),?'package.json'),?'utf-8'); }?catch(e)?{}fs.writeFile(file, data[, options], callback)
對應(yīng)著讀文件 readFile,fs 也提供了寫文件的 API writeFile,接收四個(gè)參數(shù):
第一個(gè)參數(shù): 待寫入的文件路徑
第二個(gè)參數(shù): 待寫入的文件內(nèi)容
第三個(gè)參數(shù): 配置對象,包括 encoding 和 flag,也可以直接傳如 encoding 字符串
第三個(gè)參數(shù): 回調(diào)函數(shù)
使用方法如下:
const?fs?=?require('fs'); const?path?=?require('path');fs.writeFile(path.join(process.cwd(),?'result.js'),'console.log("Hello?World")',function?(error,?content)?{console.log(error);} );同步方法
const?fs?=?require('fs'); const?path?=?require('path');try?{fs.writeFileSync(path.join(process.cwd(),?'result.js'),'console.log("Hello?World")','utf-8'); }?catch?(e)?{}本文主要是總結(jié)了一下在開發(fā) Node 時(shí)常用的一些 API,后續(xù)的文章會(huì)帶來 Node 常用的一些三方包。
參考資料
[1]
官方文檔: https://nodejs.org/dist/latest-v14.x/docs/api/
[2]DefinePlugin: https://webpack.js.org/plugins/define-plugin
[3]https://nodejs.org/dist/latest-v14.x/docs/api/fs.html: https://nodejs.org/dist/latest-v14.x/docs/api/fs.html
最近組建了一個(gè)江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你進(jìn)群。
·················?若川出品?·················
今日話題
去年清明假期開通了第二個(gè)微信號?ruochuan12,昨天突破2000好友了。清明假期打算完稿vuex4源碼文章,可惜,我是沒有完成,錯(cuò)誤的預(yù)估了工作量,和自己的惰性...我可能可以封為資深拖稿專家了。
一個(gè)愿景是幫助5年內(nèi)前端人走向前列的公眾號
可加我個(gè)人微信 ruochuan12,長期交流學(xué)習(xí)
推薦閱讀
我在阿里招前端,我該怎么幫你?(現(xiàn)在還能加我進(jìn)模擬面試群)
如何拿下阿里巴巴 P6 的前端 Offer
總結(jié)
以上是生活随笔為你收集整理的看了就会的 Node.js 三大基础模块常用 API的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flash air java_flash
- 下一篇: Taro+react开发(12)--注意