Chrome插件踩坑日志(二)vite插件手动实现“热更新”
在现在前端开发中,热更新是必不可少的配置,但是来到了chrome插件的环境中,这就是一个比较头疼的事情了,虽说市面上有一些插件和解决方案,但是v3升级带来的限制,很多方案就不能用了。最近在这方面一直探索,踩了很多坑,才有一个还算过得去的解决方案,虽然不算完美,但至少是个MVP版本了。
背景知识
v2的热更新原理
目前很多能搜到的插件热更新解决方案,可以简单理解成下图
步骤:
-
打包工具层起两个服务器,一个普通
server
,一个是websocket
-
监听打包结果文件的变化,如果有变化就通知websocket,websocket再通知浏览器
-
浏览器拿到代码更新的信号后,就对
dev-server
发起静态资源的请求 -
利用
JSONP
的原理进行代码执行覆盖
当前其中还有相当多的细节,比如hash判断,热更替,容错兜底等,其实和我们正常开发前端页面区别不大。
v3的的困境
到了V3版本的插件里,这一套方案就有点问题了,主要的环节出在JSONP
这一段,之前V2的方案里去动态加载远程代码,是需要在manifest.json
中添加配置的:
这个配置表示可以用script标签执行来自http://localhost:3333
的js资源。
V3环节中,如果还这么干,那么浏览器就会有类似如下的报错:
这个意思就是在插件环境中只能执行插件目录下的文件,其他远程或eval
的执行都会被拒。
如何平替实现(MVP)
架构图
上面就是针对V3环境进行调整的一个架构图,变动如下:
- 去掉了
devServer
这一层,改成直接输出静态文件 - 有任何更新都直接通知Background
- 对于Background有变动,那么就
reload
,ContentScript
也通过Background这个桥梁更新
hotReload细节
下图是Background的更新代码,收到通知reload即可
下图是ContentScript如何通过Background来更新代码
通过上面的代码可以知道,每次websocket发出更新的指令,就会触发对当前已打开页面执行新脚本的命令(exectuScript
)。
但是重复执行代码肯定会有隐患存在,毕竟作用域都是同一个window下的,所以下面代码就是为了清除之前留下来的节点:
自定义vite插件
在vite插件层,需要做的事情是下面两件:
- 在配置解析前启动websocket服务
- 每次Bundle打包结束就通过wss通知所有的连接进行更新代码
这里再顺便解释下为什么用writeBundle
这个钩子,因为到了这个阶段,基本可以确保文件都已经写入到了本地环境,这时候插件更新或执行代码就能实时找到,不会出现不存在的报错。
同时,这里插件定义了两种,因为在系列的第一篇文章里说过,模板里定义了两个vite配置,所以在不同环境上的代码会有所区别,比如端口差别,首次触发reload等。
实际体验
下面就来看看实际体验:
动图里左侧是按钮所在的ContentScript
代码,可以看到修改完代码后,动图的右上角的按钮很快就从蓝色变成了红色,说明热更新生效了,效果不错。
下面继续贴上仓库的地址供大家一起讨论学习:
结束
这是本系列的第二篇文章,关于Chrome插件这个题材更新起来还是挺费力的,因为目前可以参考的资料都很少,不过目前至少已经简单实现了“热更新”,在效率上有很大提升了。
创造不易,希望jym多多 点赞 + 关注 + 收藏
三连,持续更新中!!!
PS: 文中有任何错误,欢迎掘友指正
往期精彩📌
转载自:https://juejin.cn/post/7153788065012514823