介绍Compiler的构造比较无趣,不如先过后面的,在用到compiler的时候再做讲解。

  这一节主要讲这行代码:

  1. // 不管这里
  2. compiler = new Compiler();
  3. compiler.context = options.context;
  4. compiler.options = options;
  5. // 看这里
  6. new NodeEnvironmentPlugin().apply(compiler);

  这个构造了一个NodeEnvironmentPlugin对象并调用apply对compiler进行操作。

  流程图:

  模块源码如下:

  1. "use strict";
  2.  
  3. const NodeWatchFileSystem = require("./NodeWatchFileSystem");
  4. const NodeOutputFileSystem = require("./NodeOutputFileSystem");
  5. const NodeJsInputFileSystem = require("enhanced-resolve/lib/NodeJsInputFileSystem");
  6. const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem");
  7.  
  8. class NodeEnvironmentPlugin {
  9. apply(compiler) {
  10. // 可以缓存输入的文件系统
  11. compiler.inputFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 60000);
  12. const inputFileSystem = compiler.inputFileSystem;
  13. // 输出文件系统
  14. compiler.outputFileSystem = new NodeOutputFileSystem();
  15. // 监视文件系统
  16. compiler.watchFileSystem = new NodeWatchFileSystem(compiler.inputFileSystem);
  17. // 添加事件流before-run
  18. compiler.plugin("before-run", (compiler, callback) => {
  19. if (compiler.inputFileSystem === inputFileSystem)
  20. inputFileSystem.purge();
  21. callback();
  22. });
  23. }
  24. }
  25. module.exports = NodeEnvironmentPlugin;

  除去添加事件流,其余几步都是在compiler对象上挂载node的fs文件系统,详细的API用法可以去nodejs官网看文档:https://nodejs.org/dist/latest-v8.x/docs/api/

  这里只做简介:

NodeJsInputFileSystem

  1. var fs = require("graceful-fs");
  2.  
  3. module.exports = NodeJsInputFileSystem;
  4. // 获取文件信息
  5. NodeJsInputFileSystem.prototype.stat = fs.stat.bind(fs);
  6. // 读取目录内容
  7. NodeJsInputFileSystem.prototype.readdir = function readdir(path, callback) {
  8. // files 是目录中不包括 '.' 和 '..' 的文件名的数组
  9. fs.readdir(path, function(err, files) {
  10. callback(err, files && files.map(function(file) {
  11. // 对文件名进行NFC格式化
  12. return file.normalize ? file.normalize("NFC") : file;
  13. }));
  14. });
  15. };
  16. // 读取文件
  17. NodeJsInputFileSystem.prototype.readFile = fs.readFile.bind(fs);
  18. // 读取链接
  19. NodeJsInputFileSystem.prototype.readlink = fs.readlink.bind(fs);
  20. // 同步方法
  21. NodeJsInputFileSystem.prototype.statSync = fs.statSync.bind(fs);
  22. NodeJsInputFileSystem.prototype.readdirSync = function readdirSync(path) {/**/};
  23. NodeJsInputFileSystem.prototype.readFileSync = fs.readFileSync.bind(fs);
  24. NodeJsInputFileSystem.prototype.readlinkSync = fs.readlinkSync.bind(fs);

  可以看到,这里只是对引入的graceful-js的部分方法进行bind绑定,大概看一下graceful-fs的内容:

  1. var fs = require('fs')
  2.  
  3. // ...工具方法
  4.  
  5. module.exports = patch(require('./fs.js'))
  6. if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) {
  7. module.exports = patch(fs)
  8. }
  9.  
  10. module.exports.close = fs.close = (function(fs$close) { /*...*/ })(fs.close)
  11.  
  12. module.exports.closeSync = fs.closeSync = (function(fs$closeSync) { /*...*/ })(fs.closeSync)
  13.  
  14. function patch(fs) {
  15. // fs方法二次封装
  16. return fs
  17. }

  跟名字一样,内部调用了一个patch对fs模块进行二次封装,变得更加'优雅'。

NodeOutputFileSystem

  1. "use strict";
  2.  
  3. const fs = require("fs");
  4. const path = require("path");
  5. const mkdirp = require("mkdirp");
  6.  
  7. class NodeOutputFileSystem {
  8. constructor() {
  9. // 新建多层级文件夹
  10. this.mkdirp = mkdirp;
  11. // 新建单个文件夹
  12. this.mkdir = fs.mkdir.bind(fs);
  13. // 删除文件夹
  14. this.rmdir = fs.rmdir.bind(fs);
  15. // 删除文件
  16. this.unlink = fs.unlink.bind(fs);
  17. // 将内容写进某个文件
  18. this.writeFile = fs.writeFile.bind(fs);
  19. // 略
  20. this.join = path.join.bind(path);
  21. }
  22. }
  23.  
  24. module.exports = NodeOutputFileSystem;

  这个模块就十分亲民,都是原生的nodeAPI,并没有进行包装。

NodeWatchFileSystem

  1. "use strict";
  2.  
  3. const Watchpack = require("watchpack");
  4.  
  5. class NodeWatchFileSystem {
  6. constructor(inputFileSystem) {
  7. this.inputFileSystem = inputFileSystem;
  8. this.watcherOptions = {
  9. aggregateTimeout: 0
  10. };
  11. this.watcher = new Watchpack(this.watcherOptions);
  12. }
  13. // 对文件进行监视
  14. watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) { /*...*/ }
  15. }
  16.  
  17. module.exports = NodeWatchFileSystem;

  模块内容比较简单,引入一个inputFileSystem进行初始化监视对象,原型上只有一个watch方法。(实际内容非常深入和繁杂,后面再讲)

  

  这个模块主要是为了接下来输出打包文件做准备,主要内容大部分是nodejs相关。

  不过没关系,都是用JS写的。

.9-浅析webpack源码之NodeEnvironmentPlugin模块总览的更多相关文章

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

    剩下一个watch模块,这个模块比较深,先大概过一下整体涉及内容再分部讲解. 流程图如下: NodeWatchFileSystem const Watchpack = require("wa ...

  2. .3-浅析webpack源码之预编译总览

    写在前面: 本来一开始想沿用之前vue源码的标题:webpack源码之***,但是这个工具比较巨大,所以为防止有人觉得我装逼跑来喷我(或者随时鸽),加上浅析二字,以示怂. 既然是浅析,那么案例就不必太 ...

  3. .6-浅析webpack源码之validateSchema模块

    validateSchema模块 首先来看错误检测: const webpackOptionsValidationErrors = validateSchema(webpackOptionsSchem ...

  4. .4-浅析webpack源码之convert-argv模块

    上一节看了一眼预编译的总体代码,这一节分析convert-argv模块. 这个模块主要是对命令参数的解析,也是yargs框架的核心用处. 生成默认配置文件名数组 module.exports = fu ...

  5. .15-浅析webpack源码之WebpackOptionsApply模块-plugin事件流总览

    总体过了一下后面的流程,发现Compiler模块确实不适合单独讲解,这里继续讲解后面的代码: compiler.options = new WebpackOptionsApply().process( ...

  6. .14-浅析webpack源码之Watchpack模块

    解决掉了最头疼的DirectoryWatcher内部实现,这一节可以结束NodeWatchFileSystem模块. 关于watch的应用场景,仔细思考了下,这不就是热重载的核心嘛. 首先是监视文件, ...

  7. .13-浅析webpack源码之WatcherManager模块

    从模块流可以看出,这个NodeWatchFileSystem模块非常深,这里暂时不会深入到chokidar模块,有点太偏离本系列文章了,从WatcherManager开始讲解. 流程如图: 源码非常简 ...

  8. .11-浅析webpack源码之Storage模块

    至此已完成NodeJsInputFileSysten模块的讲解,下一步就是实际实用的模块: compiler.inputFileSystem = new CachedInputFileSystem(n ...

  9. .10-浅析webpack源码之graceful-fs模块

    在cachedInput.output.watch三大文件系统中,output非常简单,没有必要讲,其余两个模块依赖于input模块,而input主要是引用了graceful-fs的部分API,所以这 ...

随机推荐

  1. 使用bower init创建bower.json文件

    使用bower init 可以快速创建bower.json文件 bower init 回答一系列问题后就可以了,其中大部分问题可以按enter跳过.

  2. 分布式数据库TiDB的部署

    转自:https://my.oschina.net/Kenyon/blog/908370 一.环境 CentOS Linux release 7.3.1611 (Core)172.26.11.91   ...

  3. Brave Game(裸的巴什博弈)

    Brave Game Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  4. scanf和cin性能的比较

    我的实验机器配置是: 处理器:Intel(R) Core(TM) i3-7100U CPU @ 2.40GHz 2.40GHz 随机访问存储器:4.00GB 操作系统:Windows10 集成开发环境 ...

  5. Maven合并多个war包的工程需要用到的插件

    <build> <finalName>WebSite</finalName> <plugins> <!-- 配置war包合并的插件 --> ...

  6. Vue.js优雅的实现列表清单

        一.Vue.js简要说明 Vue.js (读音 /vjuː/) 是一套构建用户界面的渐进式框架.与前端框架Angular一样, Vue.js在设计上采用MVVM模式,当View视图层发生变化时 ...

  7. SQL server中事务的四个属性特征(ACID)

    事务的概念.类型和四个特征(ACID). 1.事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位. 通过事务,SQL Se ...

  8. JS中!=、==、!==、===的用法和区别

    1.对于string,number等基础类型,==和===是有区别的 1)不同类型间比较,==之比较"转化成同一类型后的值"看"值"是否相等,===如果类型不同 ...

  9. JS小游戏:贪吃蛇(附源码)

    javascript小游戏:贪吃蛇 此小游戏采用的是面向对象的思想,将蛇,食物,和游戏引擎分为3个对象来写的. 为方便下载,我把js写在了html中, 源码中暂时没有注释,等有空我在添加点注释吧. 游 ...

  10. Java中static关键字的详解

    static关键字可以修饰方法和成员变量(不可以修饰局部变量,但是可以修饰内部类). static关键字方便在没有创建对象的情况下来进行调用(方法/变量). 很显然,被static关键字修饰的方法或者 ...