一种很新的脚本开发方式——Selector HMR ?!
本帖最后由 LinLin00 于 2023-12-23 01:23 编辑此前,我们已经有了 (https://github.com/LinLin00000000/usbuild) 这样一个开发工具,它拥有开发模式实时热重载的功能。
这个实时热重载就是监听你脚本源文件的变化,一有变化就会通知浏览器,然后浏览器进行页面刷新,免去了手动刷新的麻烦。
但是,即使有了 autoReloadDelay 这样的控制自动刷新间隔的参数,在元素繁多的页面进行频繁刷新也会产生一点不好的体验,因为刷新慢加载慢,再加上一般需要开着浏览器调试工具,会感觉到明显的卡。
我去找了另一个比较有名的构建工具 (https://github.com/lisonge/vite-plugin-monkey),它在搭配一些前端框架如 Vue、React 使用时可以对里面的前端页面实现 HMR,但一般我开发脚本都是使用 document.querySelector 获取页面上的元素进行一些修改,而不是直接塞一个前端框架在旁边。当我在它的 dev 模式中使用 document.querySelector 对页面元素做修改时,无法享受到 vite 的 hmr 功能,也是只能把整个网页重新加载。
于是我给我的工具加了一个实验性功能(尚未发布),可以在监听到文件变化时不直接刷新浏览器,而是进行动态地重新安装脚本,再加上一点小小的魔法(后面会讲到),就可以实现 Selector 级别的 HMR,下面直接看效果
![演示动画.gif](data/attachment/forum/202312/23/005410od2fqui2ddcuuniz.gif)
(竟然只支持 1MB 以下的图片,只能压缩得非常糊)
原理其实很简单,虽然每次都会重新安装脚本,但是只要在 unsafeWindow 上存储一个 cache 就行了,每次运行的时候先找有没有 cache,有就先恢复元素最初的样子,然后再执行用户自定义的 callback。其实就是简单封装一下 (https://bbs.tampermonkey.net.cn/thread-5561-1-1.html)
有一些局限性,需要做好缓存和恢复的工作,还要处理好副作用,可以考虑抽象出一个通用的插件 {save(), load(), update()} 就可以适用更多场合。
```JavaScript
const selectorHMR = (selector, callback, options) => {
const CACHE_NAME = '_usbuild_selectorHMR'
if (!unsafeWindow) {
unsafeWindow = new Map()
}
const cacheMap = unsafeWindow
const uuid = selector
let cache
if (cacheMap.has(uuid)) {
console.log(`cache | ${uuid} | load`)
cache = cacheMap.get(uuid)
cache.remove()
dynamicQuery(selector, e => (e.outerHTML = cache.originHTML), options)()
cache.remove = dynamicQuery(selector, callback, options)
} else {
console.log(`cache | ${uuid} | save`)
cache = {}
cacheMap.set(uuid, cache)
cache.remove = dynamicQuery(
selector,
e => {
cache.originHTML = e.outerHTML
callback?.(e)
},
options
)
}
return cache.remove
}
```
ggnb!
这样的话,这样需要手动控制?感觉全局热重载够了,生产环境的时候不会用到这个
或者还有些什么场景呢?不过代码值得学习!
王一之 发表于 2023-12-23 09:56
ggnb!
这样的话,这样需要手动控制?感觉全局热重载够了,生产环境的时候不会用到这个
不太明白你说的手动控制是什么意思?我感觉开发流程已经非常自动化了。
当然是开发才用,生产模式的话直接打包部署了。
全局热重载频繁刷新有时候体验并不好,或者就是有些页面你刷新一次会带来比较严重的副作用,就可以采用这种不刷新页面的方法。
这确实可以解决一些我开发脚本的痛点,不过这应该也就是我个人用用了,封装成库需要做的事情很多,比直接刷新页面复杂多了。 LinLin00 发表于 2023-12-23 12:01
不太明白你说的手动控制是什么意思?我感觉开发流程已经非常自动化了。
当然是开发才用,生产模式的话直 ...
我的手动控制的意思是:我要用selectorHMR这个方法指定局部,才能使用这个局部热重载功能
临时debug应该很好用 本帖最后由 LinLin00 于 2023-12-23 15:37 编辑
王一之 发表于 2023-12-23 13:59
我的手动控制的意思是:我要用selectorHMR这个方法指定局部,才能使用这个局部热重载功能
临时debug应该 ...
确实是这样,得自己主动控制让哪一部分带上 HMR 功能,但是指定之后可以给开发调试提供很大的便利,磨刀不误砍柴工吧😋
毕竟没有网页源码,不能自动全局热重载,只能以这样 hack 的方式实现局部热重载。
或者有没有这样一个说法,开发的时候直接把目标网页 clone 到本地,使其变成静态页面,然后脚本源文件一有变动直接刷新页面,如果是本地开发的话体验就很好了,随便全局刷新
LikD__0812
想合作 LiuYS 发表于 2023-12-23 21:39
LikD__0812
想合作
合作什么呢? 请教一下,如果我有多个脚本需要开发,那么能否通过配置实现,还是说只能创建不同的monkey项目,比如:!(data/attachment/forum/202401/29/133009tu0771sflwwqq7fo.png)
main和main2是不同的脚本。我可以通过配置实现吗 LinLin00 发表于 2023-12-23 15:33
确实是这样,得自己主动控制让哪一部分带上 HMR 功能,但是指定之后可以给开发调试提供很大的便利,磨刀不 ...
我的项目就是本地开发的,https://bbs.tampermonkey.net.cn/thread-2840-1-1.html
模板:https://github.com/Eished/tampermonkey-template
完整项目:https://github.com/Eished/jkforum_helper ggnb!!!
页:
[1]
2