分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

.12-浅析webpack源码之NodeWatchFileSystem模块总览

发布时间:2023-09-06 01:31责任编辑:胡小海关键词:webpackNode

  剩下一个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类,并根据传入参数调用类的watch方法

4、绑定两个一次性事件绑定并返回了一个对象

  模块核心的方法调用的是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、根据构造函数的代码,监视的操作包含(可能不限于)新增文件、新增文件夹、改变内容、删除文件、删除文件夹等

  所有的模块整理如上,下面几节再来剖析每一块内容。

.12-浅析webpack源码之NodeWatchFileSystem模块总览

原文地址:http://www.cnblogs.com/QH-Jimmy/p/8059129.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved