webpack的watch选项不工作原因分析

今天尝试将以前创建的一个前端项目改为webpack编译,该项目使用了VueJS v2.0,原来是编写gulp脚本完成构建的。很自然就直接用vue-cli来搞定这个事了。

使用vue-cli创建项目

因为以前用过webpack,而vue-cli创建的项目底层其实还是使用webpack构建的,所以使用起来还是很简单的。

# 使用yarn,这个命令是跟npm兼容的,但速度快很多,而且可以保证依赖包版本的一致性,强烈推荐
yarn install --global vue-cli
vue-cli webpack vue-demo
cd vue-demo
# 安装项目依赖
yarn install
# 启动开发服务器
yarn run dev

发现问题

但我在开发过程中发现问题了,在IDE中修改了vue文件,webpack开发服务器并不会重新编译对应的模块,更不会reload浏览器页面,webpack的watch选项失效了。

在网上搜索了下原因,发现webpack的一个issue项。尝试按该问题中的说明在vue-demo/build/dev-server.js的23行加入watchOptions.polling选项,发现问题真的解决了。

var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  quiet: true,
  // Reportedly, this avoids CPU overload on some systems.
  // https://github.com/facebookincubator/create-react-app/issues/293
  watchOptions: {
    poll: true
  }
})

深究问题

watchOptions.polling选项是控制webpack如何检测文件变动的,webpack默认是采用监听文件系统变动事件来感知文件变动的,如果开启这个选项,则会定时询问文件系统是否有文件变动。现在开启这个选项,则功能正常,不开启功能不正常?而vue-cli的广大使用者并没有报告存在该问题。

个人感觉不应该是webpack的这个功能有问题,还是应该是环境问题。继续翻查资料,终于在webpack的官方文档中找到说明https://webpack.github.io/docs/troubleshooting.html#watching。这里说得很清楚,watch功能不起作用一般来说就是这几个原因。

而我现在的开发操作系统是Windows,那么就只剩下2个可能原因了。

  1. windows路径问题
  2. IDE的safe write特性干扰

试了一下终于发现是IDE的safe write特性这个问题造成的。IDE的这个特性是为了安全地写文件,它会先将文件写到一个临时文件里,然后最后一个原子move操作将文件move到目标位置。但这样webpack检测文件变动的原来逻辑就不工作了。代码见webpack/lib/node/NodeWatchFileSystem.js

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var Watchpack = require("watchpack");

function NodeWatchFileSystem(inputFileSystem) {
	this.inputFileSystem = inputFileSystem;
	this.watcherOptions = {
		aggregateTimeout: 0
	};
	this.watcher = new Watchpack(this.watcherOptions);
}

module.exports = NodeWatchFileSystem;

NodeWatchFileSystem.prototype.watch = function watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) {
	if(!Array.isArray(files))
		throw new Error("Invalid arguments: 'files'");
	if(!Array.isArray(dirs))
		throw new Error("Invalid arguments: 'dirs'");
	if(!Array.isArray(missing))
		throw new Error("Invalid arguments: 'missing'");
	if(typeof callback !== "function")
		throw new Error("Invalid arguments: 'callback'");
	if(typeof startTime !== "number" && startTime)
		throw new Error("Invalid arguments: 'startTime'");
	if(typeof options !== "object")
		throw new Error("Invalid arguments: 'options'");
	if(typeof callbackUndelayed !== "function" && callbackUndelayed)
		throw new Error("Invalid arguments: 'callbackUndelayed'");
	var oldWatcher = this.watcher;
	this.watcher = new Watchpack(options);

	if(callbackUndelayed)
		this.watcher.once("change", callbackUndelayed);

	this.watcher.once("aggregated", function(changes) {
		if(this.inputFileSystem && this.inputFileSystem.purge) {
			this.inputFileSystem.purge(changes);
		}
		var times = this.watcher.getTimes();
		callback(null, changes.filter(function(file) {
			return files.indexOf(file) >= 0;
		}).sort(), changes.filter(function(file) {
			return dirs.indexOf(file) >= 0;
		}).sort(), changes.filter(function(file) {
			return missing.indexOf(file) >= 0;
		}).sort(), times, times);
	}.bind(this));

	this.watcher.watch(files.concat(missing), dirs, startTime);

	if(oldWatcher) {
		oldWatcher.close();
	}
	return {
		close: function() {
			this.watcher.close();
		}.bind(this),
		pause: function() {
			this.watcher.pause();
		}.bind(this)
	};
};

最终关闭了IDE的safe write特性。

总结

研究这个坑的原因花了一个多小时,在此记录一下。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小二的折腾日记

面试总结-链接

https://blog.csdn.net/CCUTwangning/article/details/70153589 天下无难试之Redis面试题刁难大全 h...

8110
来自专栏草根专栏

.NET Core TDD 前传: 编写易于测试的代码 -- 全局状态

全局状态, 也可以叫做应用程序状态, 它是一组变量, 这些变量维护着应用程序的高级状态.

10430
来自专栏Java编程技术

MySQL 中基于 XA 实现的分布式事务

Xa主要规定了RM与TM之间的交互,下面来看下XA规范中定义的RM 和 TM交互的接口:

14630
来自专栏运维前线

Ngxtop-Nginx日志实时分析利器

ngxtop实时解析nginx访问日志,并且将处理结果输出到终端,功能类似于系统命令top,所以这个软件起名ngxtop。有了ngxtop,你可以实时了解到当前...

438100
来自专栏林冠宏的技术文章

关于java连接mysql数据库的几个问题的解决方法。

今天就为了连接下数据库获取信息来提供给ListView使用,搞了足足5小时。 出现的问题有:       第一个是,DriverManager.getConne...

20460
来自专栏烂笔头

SSDB安装配置记录

目录[-] SSDB的性能很突出,与Redis基本相当了,Redis是内存型,容量问题是弱项,并且内存成本太高,SSDB针对这个弱点,使用硬盘存储,使用G...

47380
来自专栏Java大联盟

Java面试手册:JDBC

14010
来自专栏腾讯云Elasticsearch Service

logstash input插件开发

logstash作为一个数据管道中间件,支持对各种类型数据的采集与转换,并将数据发送到各种类型的存储库,比如实现消费kafka数据并且写入到Elasticsea...

79340
来自专栏前端杂货铺

服务端事件EventSource揭秘

服务端推 服务端推,指的是由服务器主动的向客户端发送消息(响应)。在应用层的HTTP协议实现中,“请求-响应”是一个round trip,它的起点来自客户端,因...

34350
来自专栏hanlp学习笔记

HanLP分词器的使用方法

之前我有想过用机器学习的方法来进行词法分析,但是在项目中测试时正确率不够。于是这时候便有了 HanLP-汉语言处理包 来进行提取关键词的想法。

20900

扫码关注云+社区

领取腾讯云代金券