手机版

node.js监控文件变更的实现方法

时间:2021-08-25 来源:互联网 编辑:宝哥软件园 浏览:

前言

随着前端技术的快速发展,前端开发也在从最初的刀耕火种向工程效率方向发展。除了各种开发框架,打包、编译等技术也层出不穷,开发体验越来越好。例如,HMR让我们的更新立即可见,并告别手动F5。它的实现是监控文件变化并自动调用构建过程。下面我们来关注一下如何实现节点对文件变化的监控。

事件

假设您想监听index.js,并在内容发生变化时重新编译它。

我们使用一个简单的控制台来识别编译的执行。下面就来实现这个功能。

节点本地应用编程接口

fs.watchFile

向下看节点的文档,会看到一个符合我们需求的Apifs.watchFile(毕竟是文件相关的操作,大概在fs模块下)。

FS。watchfile (filename [,options],listener)文件名显然是文件名。options可选对象包含以下两个属性:监视持久文件时进程是否继续,默认的真实时间间隔多久旋转一次目标文件?默认的5007毫秒侦听器事件回调包含两个参数:当前当前文件stat对象prev上一个文件stat对象。看完参数信息,不知道大家从它的参数属性中有没有得到什么特别的信息。尤其是监听器中的间隔选项和回调参数。

监控与文件名对应的文件,并在文件被访问时触发回调。

每当在这里访问文件时触发,实际上意味着每次切换后都会重新输入文件,然后保存后,不管是否修改,回调都会启动。

此外,轮询事件和文件对象可以猜测是否实现了监控原理,定时轮询文件状态,然后返回前后状态,并给用户判断。

因此,node还建议,如果想要得到文件修改,需要根据stat对象的修改时间进行比较,即比较curr.mtime和prev.mtime

这就是问题。先看例子,会更清楚。

const fs=require(' fs ')const file path='。/index.js' console.log(`侦听$ { filePath } `);fs.watchFile(filePath,(cur,Prv)={if (filePath) {//打印出修改时间console . log(` cur . mtime $ { cur . mtime . to local string()} `)console . log(` Prv . mtime $ { Prv . mtime . to local string()} `)/。=PRV . mtime){ console . log(` $ { file path }文件已更新`)}})和测试结果如下:

//运行节点watch1.js//. 1。不加修改地访问index.js,然后保存。//2.切换文件,不修改再次访问,只报告错误。//3.编辑内容并保存

我们可以看到步骤1和2,实际上没有修改内容,但是我们没有办法区分它们。只要切换后保存,修改后的时间戳mtime就会改变。

另外,响应时间真的很慢,毕竟是轮询。

对于这些问题,其实官网也给出了一句话:

使用fs.watch()比fs.watchFile和fs.unwatchFile更有效。应该尽可能使用fs.watch而不是fs.watchFile和fs.unwatchFile。

如果可以使用fs.watch,就不要使用watchFile。一是效率;第二,我们无法准确知道修改状态;第三,我们只能监控单个文件。在实际开发过程中,我们显然要注意源文件夹的变化。

fs.watch

第一种用法如下:

fs.watch(文件名[,选项] [,侦听器])类似于fs.watchFile.

文件名显然是文件名选项可选对象或者字符串包含以下三个属性:进程是否在持久文件被监控时继续,所有子目录是否被默认真递归监控,默认假是当前目录,真是所有子目录。编码指定传递给回调事件的文件名。默认的utf8侦听器事件回调包含两个参数:eventType事件类型、重命名或更改文件名。如果是字符串,options指的是编码。

听文件名对应的文件或文件夹(这个特性也体现在递归参数中),返回一个fs。FSWatcher对象。

该功能的实现依赖于来自底层操作系统的文件更改通知。因此,就出现了不同平台的实现可能不一样的问题。以下示例1:

const fs=require(' fs ')const file path='。/'console.log(`侦听$ { filePath } `);fs.watch (filepath,(event,filename)={ if(filename){ console . log(` $ { filename }文件更新了`)}}的一个明显的优点是:响应及时,效率肯定比轮询高。

但是,当您以这种方式修改和保存它时,您会发现也存在一些问题。

直接保存并显示两个更新

修改文件后,更新也会显示两次(在mac系统上显示两次,在其他系统中可能会有所不同)

这可能与操作系统对文件修改的事件支持有关,文件修改在保存时多次启动。

下面重点介绍回调事件的参数。事件对应于事件类型。你能在执行之前判断事件类型是否改变吗?空保存被忽略。

const fs=require(' fs ')const file path='。/'console.log(`侦听$ { filePath } `);FS.watch (filepath,(event,filename)={ console . log(` event type $ { event } `)if(filename event==' change '){ console . log(`$ { filename }文件被更新`)})但实际上,一个空的已保存事件也是一个更改。此外,不同平台的事件,这种方式传递。

检查更改时间

显然,从上面的例子可以看出,变化时间仍然是不可控的。因为节点对应的stat对象在每次保存时仍然会被修改。

比较文档内容

只能选择这种方式来判断是否更新。例如md5:

const fs=require('fs '),MD5=require(' MD5 ');Const filepath='。/'让prevemd5=nullconsole.log(`侦听${filePath} `);fs.watch(filePath,(event,filename)={ var current D5=Md5(fs . readfilesync(filePath filename))if(current D5==previemd5){ return } previemd5=current D5 console . log(` $ { file path }文件已更新`)})首先保存当前文件的MD5值。当文件发生变化时(即保存操作响应后),每次获取文件的md5并进行比较,看是否发生变化。

但是,可以看到第一次保存将执行一次,因为初始值为空。这样就可以添加一个兼容性,并判断是否是第一次保存。

最佳化

对于不同的操作系统,保存时可能会触发多个回调(它不会出现在mac上)。为了避免这种实时响应对应的频繁触发,可以引入去抖功能来保证性能。

const fs=require('fs '),MD5=require(' MD5 ');让prevemd5=null,fswait=false const filepath='。/'console.log(`侦听$ { filePath } `);fs.watch(filePath),(事件,文件名)={ if(文件名){ if(fsWait)return;fsWait=setTimeout(()={ fsWait=false;},100) var currentmd5=MD5 (fs。readfilesync(file path filename))if(current D5==previemd 5){ return } previemd 5=current D5 console . log(`$ { file path }文件已更新`)}})

至此,节点监听文件的实现结束。做一个学习笔记,做一个参考记录。不难实现,但要想在实践中应用,需要考虑很多方面。或者推荐一些开源框架,比如node-watch和chokidar,它们在各个方面都实现得很好。

好了,这就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。谢谢你的支持。

参考文章

节点文档如何在node.js中监视文件更改nodejs监视文件更改

版权声明:node.js监控文件变更的实现方法是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。