.12-淺析webpack源碼之NodeWatchFileSystem模塊總覽

  剩下一個watch模塊,這個模塊比較深,先大概過一下整體涉及內容再分部講解。

  流程圖如下:

NodeWatchFileSystem

const Watchpack = require("watchpack");class NodeWatchFileSystem {constructor(inputFileSystem) {this.inputFileSystem = inputFileSystem;this.watcherOptions = {aggregateTimeout: 0};this.watcher = new Watchpack(this.watcherOptions);}watch(files, /*Array*/dirs, /*Array*/missing, /*Array*/startTime, /*number*/options, /*object*/callback, /*function*/callbackUndelayed /*function*/) {// params validate...const oldWatcher = this.watcher;// 生成Watchpack對象this.watcher = new Watchpack(options);if (callbackUndelayed)this.watcher.once("change", callbackUndelayed);this.watcher.once("aggregated", (changes, removals) => { /**/ });// 調用watch方法this.watcher.watch(files.concat(missing), dirs.concat(missing), startTime);if (oldWatcher) {oldWatcher.close();}return {close: () => { /**/ },pause: () => { /**/ }};}
}module.exports = NodeWatchFileSystem;

  除去細節代碼,該模塊大體如下;

1、引入Watchpack模塊

2、接受一個inputFileSystem作為構造函數的參數

3、根據配置選項實例化一個Watchpack類

4、核心watch方法為調用實例類的watch方法,傳入給定參數,綁定兩個一次性事件綁定并返回了一個對象

  模塊核心的方法調用的是Watchpack實體類上的,所以需要進一步探究該類。

  該模塊涉及到了nodejs的event模塊,內容非常簡單,這里就不做介紹了,詳情可查看官網API:https://nodejs.org/dist/latest-v8.x/docs/api/events.html

?

Watchpack

var watcherManager = require("./watcherManager");
var EventEmitter = require("events").EventEmitter;
Watchpack.prototype = Object.create(EventEmitter.prototype);class Watchpack {constructor(options) {EventEmitter.call(this);if (!options) options = {};if (!options.aggregateTimeout) options.aggregateTimeout = 200;this.options = options;this.watcherOptions = {ignored: options.ignored,poll: options.poll};this.fileWatchers = [];this.dirWatchers = [];this.mtimes = Object.create(null);this.paused = false;this.aggregatedChanges = [];this.aggregatedRemovals = [];this.aggregateTimeout = 0;this._onTimeout = this._onTimeout.bind(this);}watch(files, directories, startTime) {this.paused = false;var oldFileWatchers = this.fileWatchers;var oldDirWatchers = this.dirWatchers;this.fileWatchers = files.map(function(file) {return this._fileWatcher(file, watcherManager.watchFile(file, this.watcherOptions, startTime));}, this);this.dirWatchers = directories.map(function(dir) {return this._dirWatcher(dir, watcherManager.watchDirectory(dir, this.watcherOptions, startTime));}, this);oldFileWatchers.forEach(function(w) {w.close();}, this);oldDirWatchers.forEach(function(w) {w.close();}, this);};pause() { /**/ };getTimes() { /**/ };_fileWatcher(file, watcher) { /**/ };_dirWatcher(item, watcher) { /**/ };_onChange(item, mtime, file) { /**/ };_onRemove(item, file) { /**/ };_onTimeout() { /**/ };close() { /**/ };
}module.exports = Watchpack;function addWatchersToArray(watchers, array) { /**/ }

  本模塊引入了并繼承了nodejs的EventEmitter,并引入了新模塊watcherManager,主要內容羅列如下:

1、構造函數接受一個對象,鍵包括aggregateTimeout、ignored、poll,本例只傳入第一個并設置為0

2、核心方法為watch,依賴于引入的watchManager模塊

3、其余方法均為工具方法

?

WatcherManager

var path = require("path");class WatcherManager {constructor() {this.directoryWatchers = {};};// 工廠函數
    getDirectoryWatcher(directory, options) {// 引入模塊var DirectoryWatcher = require("./DirectoryWatcher");options = options || {};var key = directory + " " + JSON.stringify(options);if (!this.directoryWatchers[key]) {this.directoryWatchers[key] = new DirectoryWatcher(directory, options);// 文件監視結束則從容器刪除this.directoryWatchers[key].on("closed", function() {delete this.directoryWatchers[key];}.bind(this));}return this.directoryWatchers[key];};// 監視文件
    watchFile(p, options, startTime) {var directory = path.dirname(p);return this.getDirectoryWatcher(directory, options).watch(p, startTime);};// 監視目錄
    watchDirectory(directory, options, startTime) {return this.getDirectoryWatcher(directory, options).watch(directory, startTime);};
}
module.exports = new WatcherManager();

  可以看出這是一個中間處理函數,其中構造函數生成了一個容器,容器的鍵為目錄+參數生成的一個字符串,當監視關閉后會并立即刪除。

  這個模塊類似于tapable,是一個監視對象管理器。

?

  然后是監視核心實現模塊,模塊內容比較多,這里只簡單看一下構造函數以及watch方法:

var EventEmitter = require("events").EventEmitter;
var async = require("async");
var chokidar = require("chokidar");
var fs = require("graceful-fs");class Watcher {constructor(directoryWatcher, filePath, startTime) {EventEmitter.call(this);this.directoryWatcher = directoryWatcher;this.path = filePath;this.startTime = startTime && +startTime;this.data = 0;};checkStartTime(mtime, initial) { /**/ };close() { /**/ };
}function DirectoryWatcher(directoryPath, options) {EventEmitter.call(this);this.options = options;this.path = directoryPath;this.files = Object.create(null);this.directories = Object.create(null);this.watcher = chokidar.watch(directoryPath, {ignoreInitial: true,persistent: true,followSymlinks: false,depth: 0,atomic: false,alwaysStat: true,ignorePermissionErrors: true,ignored: options.ignored,usePolling: options.poll ? true : undefined,interval: typeof options.poll === "number" ? options.poll : undefined,disableGlobbing: true});this.watcher.on("add", this.onFileAdded.bind(this));this.watcher.on("addDir", this.onDirectoryAdded.bind(this));this.watcher.on("change", this.onChange.bind(this));this.watcher.on("unlink", this.onFileUnlinked.bind(this));this.watcher.on("unlinkDir", this.onDirectoryUnlinked.bind(this));this.watcher.on("error", this.onWatcherError.bind(this));// ...
}DirectoryWatcher.prototype.watch = function watch(filePath, startTime) {this.watchers[withoutCase(filePath)] = this.watchers[withoutCase(filePath)] || [];this.refs++;var watcher = new Watcher(this, filePath, startTime);watcher.on("closed", function() { /**/ }.bind(this));// ...return watcher;
};// ...

module.exports = DirectoryWatcher;

  從構造函數和模塊引入可以得到很多信息,如下:

1、引入了graceful-js模塊,可以看出底層還是利用nodejs的fs模塊來進行監視

2、所有的監視事件都是基于nodejs的EventEmitter模塊來進行操作

3、內部還有一個輔助類Watcher

4、根據構造函數的代碼,監視的操作包含(可能不限于)新增文件、新增文件夾、改變內容、刪除文件、刪除文件夾等

?

  async模塊是一個類似于tapable的輔助工具,用于異步處理批量方法,詳細內容可自行去網上查閱。

  構造函數中,該模塊又再次引用了chokidar模塊,并調用其watch方法進行初始化,看似調用方法,源碼簡化后如下:

class FSWatcher {// ...
}
exports.FSWatcher = FSWatcher;
exports.watch = function(paths, options) {return new FSWatcher(options).add(paths);
};

  假的,這還是個new操作,只是為了方便把兩步合成到了一個方法中。

?

  所有的模塊整理如上,下面幾節再來剖析每一塊內容。

轉載于:https://www.cnblogs.com/QH-Jimmy/p/8059129.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453857.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453857.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453857.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python 第三方模塊之 beautifulsoup(bs4)- 解析 HTML

簡單來說,Beautiful Soup是python的一個庫,最主要的功能是從網頁抓取數據。官方解釋如下:官網文檔 Beautiful Soup提供一些簡單的、python式的函數用來處理導航、搜索、修改分析樹等功能。 它是一個工具箱,通過解析文檔為用戶提供…

modal vue 關閉_Vue彈出框的優雅實踐

引言頁面引用彈出框組件是經常碰見的需求,如果強行將彈出框組件放入到頁面中,雖然功能上奏效但沒有實現組件與頁面間的解耦,非常不利于后期的維護和功能的擴展.下面舉個例子來說明一下這種做法的弊端.click"openModal()">點擊 :is_open"is_open" close…

Python 第三方模塊之 lxml - 解析 HTML 和 XML 文件

lxml是python的一個解析庫,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高 XPath,全稱XML Path Language,即XML路徑語言,它是一門在XML文檔中查找信息的語言,它最初是用來搜尋XML文…

(轉)Linux下PS1、PS2、PS3、PS4使用詳解

Linux下PS1、PS2、PS3、PS4使用詳解 原文:http://www.linuxidc.com/Linux/2016-10/136597.htm 1、PS1——默認提示符 如下所示,可以通過修改Linux下的默認提示符,使其更加實用。在下面的例子中,默認的PS1的值是“\s-\v\$”,顯示出…

開放平臺大抉擇

開放平臺大抉擇之新浪SAE:為個人應用開發帶來福音 導讀:繼上期淘寶網副總裁王文彬從平臺功能特色、運營狀況等多方面分享了淘寶開放平臺的歷程和挑戰之后。國內另一家云平臺服務方的典型代表——Sina App Engine(簡稱SAE),作為新浪研發中心于…

ip68級防水可以泡多久_iPhone8防水級別升級至IP68:能在1.5米深水中堅持30分鐘

1月15日,業界最新的泄密消息顯示,蘋果擬在今年推出的“iPhone 8”智能手機會是一款革命性的手機,功能和配置就不多說了。蘋果還將解決iPhone 7的一個重要缺陷,就是大大增強iPhone 8的防水性能,防水級別達IP68。《韓國先…

HTTP POST 發送數據的參數 application/x-www-form-urlencoded、multipart/form-data、text/plain

HTTP 簡介 HTTP/1.1 協議規定的 HTTP 請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 這幾種。 其中 POST 一般用來向服務端提交數據,本文主要討論 POST 提交數據的幾種方式。 我們知道,HTTP 協議是以 ASCII 碼傳輸,建…

vue 二進制文件的下載(解決亂碼和解壓報錯)

問題描述:項目中使用的是vue框架進行開發,因為文件下載存在權限問題,所以并不能通過 a 鏈接的 href 屬性直接賦值 URL進行下載, (如果你的文件沒有下載權限,可以直接通過href屬性賦值URL的方法進行文件下載…

Python 第三方模塊之 psutil - 獲取系統運行的進程和系統利用率信息

一、psutil模塊: 官方網址:http://pythonhosted.org/psutil/ 1.psutil是一個跨平臺庫(http://pythonhosted.org/psutil/)能夠輕松實現獲取系統運行的進程和系統利用率(包括CPU、內存、磁盤、網絡等)信息。它主要用來做系統監控,…

石頭機器人紅燈快閃_機器人集體“快閃”活動爆紅網絡 “我是AI”與您相約智能新時代...

原標題:機器人集體“快閃”活動爆紅網絡 “我是AI”與您相約智能新時代3月10日下午,天津科學技術館內,悠揚美妙的歌聲《我和我的祖國》突然響起,隨后50個身形矯健的阿爾法機器人伴隨著歌聲翩翩起舞,動作整齊、科技感十…

淺談云計算與數據中心計算

文/林仕鼎 云計算概念發端于Google和Amazon等超大規模的互聯網公司,隨著這些公司業務的成功,作為其支撐技術的云計算也得到了業界的高度認可和廣泛傳播。時至今日,云計算已被普遍認為是IT產業發展的新階段,從而被賦予了很多產業和…

無線網絡實體圖生成工具airgraph-ng

無線網絡實體圖生成工具airgraph-ngairgraph-ng是aircrack-ng套件提供的一個圖表生成工具。該工具可以根據airodump工具生成的CSV文件繪制PNG格式的圖。繪制的圖有兩種類型,分別為AP-客戶端關聯圖和通用探測圖。通過AP-客戶端關聯圖,可以更為直觀的了解無…

高等代數期末考試題庫及答案_數學類高等代數期末考試試題A卷(含答案)

數學類高等代數期末考試試題A卷(含答案)課程編號MTH17063 北京理工大學2010-2011學年第一學期2009級數學類高等代數期末考試試題A卷班級 學號 姓名 成績 一、(25分)設表示域上的所有階矩陣構成的上的線性空間。取定,對于任意的,定義。(1)證明為上的一個線…

cocos2d-lua3.7組件篇(三)-http通信demo

客戶端使用lua、服務端使用QT做為服務器。 步驟: 客戶端 -----------Post 用戶名和密碼 服務端接受Post請求,讀取數據,返回response一、客戶端代碼 loadingImg require"app.scenes.LoadingLayer"local LoginScene class(&qu…

數據挖掘:如何尋找相關項

導讀:隨著大數據時代浪潮的到來數據科學家這一新興職業也越來越受到人們的關注。本文作者Alexandru Nedelcu就將數學挖掘算法與大數據有機的結合起來,并無縫的應用在面臨大數據浪潮的網站之中。 數據科學家需要具備專業領域知識并研究相應的算法以分析對…

Python 第三方模塊之 selenium - 模擬操作 Chrome 瀏覽器

1、安裝selenium 1.1、Python 安裝 selenium 模塊 pip install selenium1.2、下載驅動 選擇和自己chrom版本相對應的驅動到本地,下載地址 http://npm.taobao.org/mirrors/chromedriver/2、Python 操作 from selenium import webdriver import time import json…

jupyter notebook代碼導出_Jupyter Notebook導出包含中文的pdf_親測有效

Jupyter Notebook是很好的數據科學創作環境,是非常方便的Python代碼編輯器。jupyter提供導出的格式有.py、.html、.md、.pdf等。目前用其導出包含中文的pdf會遇到很多坑,網上也有一些解決方案,大致分為兩種方式,一是安裝 pandoc并…

前端之使用 POST 提交數據并跳轉

GET 方式 window.location.href是我們常用來在js中實現頁面跳轉的方法,這是使用get方式發送請求,示例如下 window.location.href url;優點是簡單易用,缺點是如果有參數的話,參數會暴露在url地址中,這降低了系統的安…

cef js返回c++的代碼_CEF3開發者系列之外篇——IE中JS與C++交互

使用IE內核開發客戶端產品,系統和前端頁面之間的交互,通常給開發和維護帶來很大的便利性。但操作系統和前端之間的交互卻是比較復雜的。具體來說就是腳本語言和編譯語言的交互。在IE內核中html和css雖然不兼容,但是IE編程接口是完全一樣的,這得益于微軟的…

多線程編程指南 part 2

多線程編程指南Sun Microsystems, Inc.4150 Network CircleSanta Clara, CA95054U.S.A.文件號碼819–7051–102006 年10 月版權所有2005 Sun Microsystems, Inc. 4150 Network Circle, Santa Clara, CA95054 U.S.A. 保留所有權利。本文檔及其相關產品的使用、復制、分發和反編譯…