专栏首页jeremy的技术点滴webpack的watch选项不工作原因分析

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 条评论
登录 后参与评论

相关文章

  • SSM项目脚手架

    jeremyxu
  • golang开发环境搭建

    jeremyxu
  • 现代Web开发系列教程_05

    jeremyxu
  • 教你如何读webpack2中文文档

    经过一个多月的奋战,webpack2的中文文档已经翻译好大部份,并且完成了核心内容“概念”和“指南”部份的校对。 这份文档比react, vue之类的文档都要庞...

    李成熙heyli
  • 一篇文带你从0到1了解建站及完成CMS系统编写

    文章为从0到1了解内容管理系统搭建与编写,由于一篇文章内容篇幅过长,文章内容经过压缩,该项目中相同逻辑的实现只以一个实例作为描述,主要以核心关键功能的开发作为主...

    公众号 碧油鸡
  • PHP的socket扩展

    我们了解了常用的网络协议,今天我们来了解下socket服务。我们可以基于tcp和udp来实现我们的socket服务,

    老雷PHP全栈开发
  • 学术资讯|“人工智能与法律”对AI产品经理有何实际借鉴意义

    前图灵机器人-人才战略官/AI产品经理,前TX产品经理,垂直于“AI产品经理”的第一自媒体,行业内第一个AI产品经理的成长交流社区-饭团“AI产品经理大本营”的...

    优图实验室
  • 人类医生的终结者:深度学习医疗2016-17两次大突破

    【新智元导读】南澳大学医学专家 Luke Oakden-Rayner 发表了一系列博客文章,讨论机器会不会在短时间内取代人类医生,他总结出了医疗AI领域的 6 ...

    新智元
  • 细分网格建模

    在三维建模领域里,细分曲面算是一个比较常见的术语了,经常用于动画角色的原型设计,甚至在工业设计领域,也开始流行用细分建模来进行原型设计。教科书里一讲到细分曲面,...

    NT4.4
  • 【STM32F407开发板用户手册】第18章 STM32F407的GPIO应用之跑马灯

    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255

    armfly

扫码关注云+社区

领取腾讯云代金券