概述
由nodemon管理的服务器一般会自动监听(可配置具体监听文件)服务器的文件的修改并重启子任务,一般用于监听一个http服务器子应用,为了方便开发通常会在restart事件中执行livereload(浏览器端自动刷新),但是监听文件的类型和restart事件中却有一些问题。
注意为了结合gulp使用,这里使用的是gulp-nodemon这个包。
livereload
为了便于开发,浏览器端使用livereload插件自动刷新以获得服务器端的代码变化(笔者使用chrome,其他部分浏览器也有插件)。
nodemon的restart事件
nodemon监听指定的文件后,也可以配置指定的响应事件,在前端开发环境中,一般的需求是结合livereload做到监听源代码,保存以后响应一系列的后续任务,并最终通知浏览器重加载。
查阅nodemon官方文档中的事件可知,restart应该就是我们要监听响应的事件。因此直观地解决方案就是在restart事件中响应livereload的逻辑。代码如下。
1 | gulp.task('watch', ()=> { |
上述配置理论上应该没有问题,实际上浏览器也会自动刷新,但刷新页面的结果却是浏览器无法打开页面的状态。
因为nodemon还在没有完成启动,但livereload已经发出了刷新页面的通知。可以得出结论,restart事件并不是在nodemon重启服务器后的响应事件,而是重启开始时的响应事件,服务器还没有来得及完成重启。这显然不是我们想要的结果。
一种最暴力直接的解决方案就是使用setTimeout延迟一定时间再发出命令。代码如下。
1 | gulp.task('watch', ()=> { |
这种方案明显不够完美,但实际上,这是笔者目前在StackOverflow找到的绝大多数解决方案。
GitHub上有人给出了另一种解决方案。代码如下。
1 | gulp.task('watch', function() { |
这里监听的是readable事件,监听readable事件有一个需要注意的地方是需要配置stdout配置为false。
但遗憾的是,笔者尝试这种方式后并没有成功。
虽然目前没有找到完美的解决方案,但是由于这个是开发环境,能实现自动自动加载就能方便开发人员的工作,而且经过笔者尝试,800毫秒是一个合适的值,太快的话服务器依然未能启动,太慢的话就更影响开发体验。在没有找到更完美的解决方案之前,先只能用这种方案了。
jsx文件
笔者现在使用的前端框架主要是React,不可避免开发中会有大量jsx文件。但配置nodemon监听jsx文件却并没有作用。一般来讲nodemon就是监听指定的文件,发现变化以后根据配置,重新启动服务器,但这里却监听不到jsx文件的变动。
经过一番尝试并依然失败之后,笔者不得不放弃使用nodemon监听源文件,转而让监听源文件工作交给gulp,nodemon改为监听打包编译后的文件。
比如在上面的配置中,笔者还配置了在每次在启动服务器之前,都先将执行提前写好的compile的gulp任务,因为工作中使用的是es6,需要经过babel的一层解析(这里只是举个例子,实际上使用的是webpack),因此使用nodemon监听源文件是可以的,但是它却不响应jsx的修改。
修改后的配置,将新的监听任务独立出来交给gulp,让gulp来做编译打包的工作。打包完成之后必然生成新的文件,nodemon就监听这个新文件生成的目录。
1 | gulp.task('watch:src', ()=> { |
1 | gulp.task('watch', ()=> { |
这样也很好地解决了监听jsx的问题。