監視文件系統意味著監視特定目錄或文件的更改。

有時您可能需要持續觀察特定文件或目錄的更改。出于這個原因,我們使用像 chokidar 這樣的文件系統 Watcher 或內置的 NodeJs 文件系統方法 fs.watch()。
但是我們不會使用上面的方法,讓我來告訴你這樣做的原因。
fs.watch()
fs 提供了一個應用程序編程接口 (API),可連續監視文件的更改??梢允褂么朔椒ǜ櫸募模摲椒ǚ祷匾粋€ fs.FSWatcher 對象。在這里閱讀更多關于它的信息 fs.watch()。
缺點:
- 這種方法不可靠,每次修改都可能在監聽器中顯示多個事件。
- 將大多數更改作為重命名發出。
- 不提供遞歸查看文件樹的簡單方法。
- 不報告 macOS 上的文件名。
還有很多…
chokidar
它是最流行的文件系統觀察器,但盡管在某些情況下它可能就足夠了,但它并不完美。
優點:
- 它支持處理符號鏈接。
- 它有一些內置支持,可以在執行原子寫入時處理寫入磁盤的臨時文件,盡管在 Watcher 中忽略它們也很簡單,您可以通過忽略選項忽略它們。
- 它可以更可靠地觀察網絡連接的路徑,盡管在觀察大量文件時會導致性能問題。
- 盡管 Watcher(一個文件系統觀察程序庫,我們稍后會討論)具有更全面的測試套件并且也用于生產(例如在 Notable 中,它之前使用了 chokidar),但它經過了更多的實戰測試。
缺點:
- 它需要原生依賴才能在 macOS 下進行高效的遞歸觀察,而原生依賴可能很難使用。
- 在 windows 下它不能有效地遞歸地觀察,另一方面,Watcher(一個文件系統觀察器庫,我們將在后面討論)是建立在 Node 的 Windows 原生遞歸觀察能力之上的。
- 它無法檢測重命名。
- 如果您不需要像 globbing 這樣的功能,那么 chokidar 會不必要地膨脹您的應用程序包。
- EMFILE 錯誤沒有得到正確處理,因此如果您觀看的文件足夠多,chokidar 最終會放棄它們。
因為每種方法都有自己的缺點?,F在讓我們來看看解決方案。
Watcher
一個追求完美的文件系統觀察者,沒有原生依賴和可選的重命名檢測支持。
我自己使用過這個庫,與其他替代方案相比,我發現它非常簡單且無錯誤。
特征:
- 可靠:該庫旨在處理處理文件系統時可能出現的所有問題,包括一些最流行的無法處理的替代方案,例如 EMFILE 錯誤。
- 重命名檢測:這個庫可以選擇性地檢測文件和目錄何時被重命名,這允許您在某些情況下為您的用戶提供更好的體驗。
- 性能:在可用時使用本機遞歸監視(macOS 和 Windows),否則可以有效地手動執行。
- 沒有原生依賴:原生依賴使用起來會很痛苦,這個庫使用了其中的 0 個。
- 不臃腫:許多替代觀察者附帶可能無用且昂貴的功能,例如對通配的支持,這個庫旨在更精簡,同時仍然公開正確的抽象,讓您可以根據需要使用通配。
- TypeScript-ready:這個庫是用 TypeScript 編寫的,所以類型不是事后才想到的,而是隨庫一起提供的。
您可以在此處查看與其他觀察者的比較。
安裝:
npm install — save watcher
用法:
你會像這樣使用這個庫:
const Wattcher = require('watcher')
// Watching a single path
const watcher = new Watcher ( '/foo/bar' );
// Watching multiple paths
const watcher = new Watcher ( ['/foo/bar', '/baz/qux'] );
// Passing some options
const watcher = new Watcher ( '/foo/bar', { renameDetection: true } );
// Passing an "all" handler directly
const watcher = new Watcher ( '/foo/bar', {}, ( event, targetPath, targetPathNext ) => {} );
// Attaching the "all" handler manually
const watcher = new Watcher ( '/foo/bar' );
watcher.on ( 'all', ( event, targetPath, targetPathNext ) => { // This is what the library does internally when you pass it a handler directly
console.log ( event ); // => could be any target event: 'add', 'addDir', 'change', 'rename', 'renameDir', 'unlink' or 'unlinkDir'
console.log ( targetPath ); // => the file system path where the event took place, this is always provided
console.log ( targetPathNext ); // => the file system path "targetPath" got renamed to, this is only provided on 'rename'/'renameDir' events
});
// Listening to individual events manually
const watcher = new Watcher ( '/foo/bar' );
watcher.on ( 'error', error => {
console.log ( error instanceof Error ); // => true, "Error" instances are always provided on "error"
});
watcher.on ( 'ready', () => {
// The App just finished instantiation and may soon emit some events
});
watcher.on ( 'close', () => {
// The app just stopped watching and will not emit any further events
});
watcher.on ( 'all', ( event, targetPath, targetPathNext ) => {
console.log ( event ); // => could be any target event: 'add', 'addDir', 'change', 'rename', 'renameDir', 'unlink' or 'unlinkDir'
console.log ( targetPath ); // => the file system path where the event took place, this is always provided
console.log ( targetPathNext ); // => the file system path "targetPath" got renamed to, this is only provided on 'rename'/'renameDir' events
});
watcher.on ( 'add', filePath => {
console.log ( filePath ); // "filePath" just got created, or discovered by the watcher if this is an initial event
});
watcher.on ( 'addDir', directoryPath => {
console.log ( filePath ); // "directoryPath" just got created, or discovered by the watcher if this is an initial event
});
watcher.on ( 'change', filePath => {
console.log ( filePath ); // "filePath" just got modified
});
watcher.on ( 'rename', ( filePath, filePathNext ) => {
console.log ( filePath, filePathNext ); // "filePath" got renamed to "filePathNext"
});
watcher.on ( 'renameDir', ( directoryPath, directoryPathNext ) => {
console.log ( directoryPath, directoryPathNext ); // "directoryPath" got renamed to "directoryPathNext"
});
watcher.on ( 'unlink', filePath => {
console.log ( filePath ); // "filePath" got deleted, or at least moved outside the watched tree
});
watcher.on ( 'unlinkDir', directoryPath => {
console.log ( directoryPath ); // "directoryPath" got deleted, or at least moved outside the watched tree
});
// Closing the watcher once you are done with it
watcher.close ();
// Updating watched roots by closing a watcher and opening an updated one
watcher.close ();
watcher = new Watcher ( /* Updated options... */ );
關注七爪網,獲取更多APP/小程序/網站源碼資源!