博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.12-浅析webpack源码之NodeWatchFileSystem模块总览
阅读量:5252 次
发布时间:2019-06-14

本文共 7078 字,大约阅读时间需要 23 分钟。

  剩下一个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

你可能感兴趣的文章
【Java】详解Java解析XML的四种方法
查看>>
JS OOP编程
查看>>
哈夫曼树
查看>>
Linux 黑白界面显示
查看>>
ActiveMQ学习系列(四)----消息持久化到mysql
查看>>
JavaScript设计模式基础之面向对象的JavaScript(一)
查看>>
RabbitMQ-从基础到实战(4)— 消息的交换(中)
查看>>
mysql 索引数据结构及原理
查看>>
01.Hibernate入门
查看>>
Ubuntu 16.0.4开启 log-bin
查看>>
mongoDB的学习【小白的福音】
查看>>
软件工程的实践项目的自我目标
查看>>
sql server日期时间转字符串
查看>>
经典排序算法(PHP)
查看>>
jQuery中终止Ajax请求
查看>>
使用JS禁止页面打印,右击保存图片
查看>>
Spring boot中Spring-Data-JPA操作MySQL数据库时遇到的错误(一)
查看>>
django实现SSO
查看>>
adidas crazylight 2018 performance analysis review
查看>>
3--OC -- 点语法
查看>>