背景
- 开发静态页面修改样式时需要手动刷新页面才会在页面上看到效果比较麻烦
- 了解了热更新原理需要实践下
- 手动实现了对
websocket
的解析,趁热打铁把websocket
应用在实际项目中
原理
- 服务端监听文件改动
- 当文件有改动之后服务端发送事件通知客户端
- 客户端接收到事件之后做出对应的处理
实现
服务端监听文件改动
nodejs 在 fs
模块中提供了两个监听文件改动的方法 fs.watch
和 fs.watchFile
两个方法。
fs.watch
参考
监听文件及文件夹下的改动,通过如下方式调用:
1 | fs.watch(filename[, options], listener) |
filename
: 文件或目录options
: 可选的,如果 options 传入字符串,则它指定 encoding。 否则,options 应传入对象,属性如下:persistent
: <boolean
> 指示如果文件已正被监视,进程是否应继续运行。默认值:true
recursive
: <boolean
> 指示应该监视所有子目录,还是仅监视当前目录。这适用于监视目录时,并且仅适用于受支持的平台(参见注意事项)。默认值:false。
encoding
: <string
> 指定用于传给监听器的文件名的字符编码。默认值:utf8
。
listener
: 监听器回调有两个参数(eventType, filename)
。eventType
是rename
或change
,filename
是触发事件的文件的名称。
fs.watchFile
参考
监听特定文件的改动,通过如下方式调用:
1 | fs.watchFile(filename[, options], listener) |
filename
: 文件options
: 可选的,options 应传入对象,属性如下:persistent
: <boolean
> 指示如果文件已正被监视,进程是否应继续运行。默认值:true
。interval
: 指示轮询目标的频率(以毫秒为单位)。bigint
: 回调函数的参数对象是否为BigInts
类型。
listener
: 监听器回调有两个参数(curr, prev)
。curr
是文件修改后的fs.Stat
实例,prev
是文件修改前的fs.Stat
实例。
通知客户端
通过建立一个 websocket
服务的方式,当文件有变更的时候发送更新消息
1 | server.on('upgrade', function (req, socket, head) { |
客户端处理事件
在客户端插入建立 websocket
链接的代码,接收到更新之后重新刷新页面
1 | <script> |
其它
自动注入建立 websocket
链接的代码
返回 HTML
页面时通过正则的方式在页面中插入代码
1 | let data = fs.readFileSync(filePath) |
对文件修改监听的封装
通过封装成对应的方式,利用事件总线的模式实现事件的派发
1 | const fs = require('fs') |
优化
fs.watch
和fs.watchFile
兼容性考虑,在不兼容的平台上可以通过定时检查文件的方式判断文件是否有改动websocket
兼容性考虑,不支持的平台上降级为短轮询或长轮询的方式- 文件修改时可以在抛出的事件中提供更多的信息,事件局部文件的热更新而不用刷新整个页面