path
模塊是一個內(nèi)置模塊胖替,可幫助您以獨立于操作系統(tǒng)的方式使用文件系統(tǒng)路徑塞耕。如果要構(gòu)建支持 OSX陆淀、Linux 和 Windows 的 CLI 工具哗咆,則 path
模塊是必不可少的咽扇。
即使您正在構(gòu)建一個只在 Linux 上運行的后端服務(wù),path
模塊仍然有助于在操作路徑時避免邊緣情況洁段。
下面我們來介紹 path
模塊的基本用法,以及為什么您應(yīng)該使用 path
模塊而不是將路徑操縱成字符串共郭。
在 Node 中使用 path
模塊
path
模塊中最常用的方法是 path.join()
祠丝。該方法將一個或多個路徑段合并為一個字符串,如下所示:
const path = require('path')
path.join('/path', 'to', 'test.txt') // '/path/to/test.txt'
您可能想知道為什么要使用 path.join()
方法而不是字符串拼接除嘹。
'/path' + '/' + 'to' + '/' + 'test.txt' // '/path/to/test.txt'
['/path', 'to', 'test.txt'].join('/') // '/path/to/test.txt'
原因主要有兩個:
-
對于 Windows 支持写半。Windows 使用反斜杠(
\
)而不是正斜杠(/
)作為路徑分隔符。path.join()
會為我們處理此問題尉咕。因為path.join('data', 'test.txt')
在 Linux 和 OSX 以及 Windows 上都會返回'data/test.txt'
叠蝇。 -
用于處理邊緣情況。使用文件系統(tǒng)路徑時年缎,會彈出許多邊緣情況悔捶。例如,如果您嘗試手動連接兩個路徑单芜,您可能會意外地得到重復(fù)的路徑分隔符蜕该。
path.join()
方法為我們處理開頭和結(jié)尾的斜杠,如下所示:
path.join('data', 'test.txt') // 'data/test.txt'
path.join('data', '/test.txt') // 'data/test.txt'
path.join('data/', 'test.txt') // 'data/test.txt'
path.join('data/', '/test.txt') // 'data/test.txt'
常用的 path 方法
path
模塊還具有幾個用于提取路徑組件的方法洲鸠,例如文件擴展名或目錄堂淡。
path.extname()
方法以字符串形式返回文件擴展名:
path.extname('/path/to/test.txt') // '.txt'
就像連接兩條路徑一樣,獲取文件擴展名比最初看起來要復(fù)雜扒腕。
如果 path
以 .
為結(jié)尾绢淀,將返回 .
。如果文件無擴展名瘾腰,又不以 .
結(jié)尾皆的,或文件沒有擴展名,將返回空值居灯。
path.extname('/path/to/index.') // '.'
path.extname('/path/to/README') // ''
path.extname('/path/to/.gitignore') // ''
path
模塊還有 path.basename()
和 path.dirname()
方法祭务,分別獲取文件名(包括擴展名)和目錄。
path.basename('/path/to/test.txt') // 'test.txt'
path.dirname('/path/to/test.txt') // '/path/to'
path.parse()
方法返回一個對象怪嫌,該對象包含分為五個不同組合的路徑义锥,包括擴展名和目錄。path.parse()
方法也是不帶任何擴展名獲取文件名的方法岩灭。
path.parse('/path/to/test.txt')
/*
{
root: '/',
dir: '/path/to',
base: 'test.txt',
ext: '.txt',
name: 'test'
}
*/
使用 path.relative()
像 path.join()
和 path.extname()
這樣的方法涵蓋了大多數(shù)使用文件路徑的用例拌倍。但是 path
模塊有幾個更高級的方法,例如 path.relative()
。
path.relative(from, to)
方法根據(jù)當前工作目錄返回從 from
到 to
的相對路徑柱恤。 如果 from
和 to
都解析為相同的路徑(在分別調(diào)用 path.resolve()
之后)数初,則返回零長度字符串。
// 返回相對于第一條路徑的第二條路徑的路徑
path.relative('/app/views/home.html', '/app/layout/index.html') // '../../layout/index.html'
如果給定了相對于一個目錄的路徑梗顺,但需要相對于另一個目錄的路徑泡孩,則 path.relative()
方法非常有用。例如寺谤,流行的文件系統(tǒng)監(jiān)視庫 Chokidar 提供了相對于監(jiān)視目錄的路徑仑鸥。
const watcher = chokidar.watch('mydir')
// 如果用戶添加 mydir/path/to/test.txt,則會打印 mydir/path/to/test.txt
watcher.on('add', path => console.log(path))
這就是為什么大量的使用 Chokidar 工具变屁。如常見的 Gatsby 或 webpack眼俊,其在內(nèi)部也大量使用 path.relative()
方法。
例如粟关,Gatsby 使用 path.relative()
方法幫助同步靜態(tài)文件目錄疮胖。
export const syncStaticDir = (): void => {
const staticDir = nodePath.join(process.cwd(), `static`)
chokidar
.watch(staticDir)
.on(`add`, (path) => {
const relativePath = nodePath.relative(staticDir, path)
fs.copy(path, `${process.cwd()}/public/${relativePath}`)
})
.on(`change`, (path) => {
const relativePath = nodePath.relative(staticDir, path)
fs.copy(path, `${process.cwd()}/public/${relativePath}`)
})
}
現(xiàn)在,假設(shè)用戶向 static
目錄添加了一個新文件 main.js
闷板。Chokidar 調(diào)用 on('add')
事件處理程序澎灸,路徑設(shè)置為 static/main.js
。但是遮晚,當您將文件復(fù)制到 /public
時击孩,不需要額外的 static/
。
調(diào)用 path.relative('static', 'static/main.js')
返回 static/main.js
相對于 static
的路徑鹏漆,這正是您想要將 static
的內(nèi)容復(fù)制到 public
的路徑巩梢。
跨操作系統(tǒng)路徑和 URL
默認情況下,path
模塊會根據(jù) Node 進程運行的操作系統(tǒng)自動在 POSIX(OSX艺玲、Linux)和 Windows 模式之間切換括蝠。
但是,path
模塊確實可以在 POSIX 上使用 Windows path
模塊饭聚,反之亦然忌警。path.posix
和 path.win32
屬性分別包含 path
模塊的 Posix 和 Windows 版本。
// 返回 'path\to\test.txt'秒梳,與操作系統(tǒng)無關(guān)
path.win32.join('path', 'to', 'test.txt')
// 返回 'path/to/test.txt'法绵,與操作系統(tǒng)無關(guān)
path.posix.join('path', 'to', 'test.txt')
在大多數(shù)情況下,根據(jù)檢測到的操作系統(tǒng)自動切換 path 模塊是正確的行為酪碘。但是朋譬,使用 path.posix
和 path.win32
屬性對于總是希望輸出 Windows 或 Linux 樣式路徑的測試或應(yīng)用程序可能會有所幫助。
例如兴垦,一些應(yīng)用程序使用 path.join()
和 path.extname()
等方法處理 URL 路徑徙赢。
// 'https://api.mydomain.app/api/v2/me'
'https://api.mydomain.app/' + path.join('api', 'v2', 'me')
這種方法適用于 Linux 和 OSX字柠,但如果有人試圖將您的應(yīng)用程序部署到一些無服務(wù)器上會發(fā)生什么?
你最終會得到 https://api.mydomain.app/api\v2\me
狡赐,這不是有效的 URL窑业!如果使用 path
模塊操作 URL,則應(yīng)使用 path.posix
枕屉。