[js] 代码片段自动更新协议 1.0

本贴最后更新于 232 天前,其中的信息可能已经事过境迁

鉴于代码片段无法检查更新,写了个自动检查更新的代码片段。

只要用户安装了用户端代码片段或开发者加入了开发者端代码,且开发者代码片段中遵循以下协议即可。

协议内容

要让你的代码片段能自动检查更新,需遵循以下协议:

  1. 代码片段的注释中必须有 name,version,updateUrl 三个标记。

    比如

    // name 代码名称
    // version 版本号
    // updateUrl 更新地址
    // updateDesc 更新描述(选填)
    或
    /**
     * name 代码名称
     * version 版本号
     * updateUrl 更新地址
     * updateDesc 更新描述(选填)
     */
    或
    /* name 代码名称*/
    /* version  版本号 */
    /* updateUrl 更新地址 */
    /* updateDesc 更新描述(选填) */
    

    特别注意,updateDesc 的描述必须写在一行内,不能换行,如需换行的,可使用 <br /> 代替。

  2. updateUrl 可以是任意地址,只要这个地址返回的数据中含有 version 即可。

    比如

    http://xxx.com/path/xxx.0.0.2.js

    js 内容

    // name 代码名称
    // version 版本号
    // updateUrl 更新地址
    // updateDesc 更新描述
    

    这个地址也可以是链滴论坛帖子地址或回复帖子地址,复制方法是:点击帖子的右下角菜单,选择“查看 Markdown”,然后复制打开的网址即可。

  3. 注意,你的上述注释必须出现在你代码的前 200 行以内,否则将会被忽略。
    当有多个同名的注释时,则以第一个为准。

其他建议

另外,建议不要将用户配置放到代码里,将用户配置文件放到/data/storage/xxx.json 里,这样升级代码,用户配置不受影响。

使用效果

只要你在代码片段中遵循了上述协议,当你的代码片段更新时,自动会在思源代码片段的顶部添加一条更新信息。

image.png

使用说明

如果你是用户

把下面的代码放到思源 js 代码片段中即可,然后只要遵循了上述协议的代码,当代码更新时就会提示你啦。

https://gitee.com/wish163/mysoft/blob/main/%E6%80%9D%E6%BA%90/snippets_new_version_checker.js

可通过参数 interval 配置多久检查一次(单位小时),默认是 3 个小时。

如果你是代码片段开发者

你只需要把下面任意一个代码的内容放到你代码片段的任意位置,然后当你的代码有版本升级时,就会自动提示用户更新啦(这里成为开发者推广计划)。

普通方式

https://gitee.com/wish163/mysoft/blob/main/%E6%80%9D%E6%BA%90/snippets_new_version_checker_for_dev.js

cdn 方式

https://gitee.com/wish163/mysoft/blob/main/%E6%80%9D%E6%BA%90/snippets_new_version_checker_for_dev_cdn.js

但纯 css 的代码片段无法加入开发端代码,因为这个代码是 js 的,只能呼吁自己的用户安装自动更新用户端代码了。

原理

1 首先在页面加载 1 分钟后,会扫描所有代码片段的版本信息,放到全局变量里。
2 在版本信息中加入必要的字段。
3 然后页面加载 2 分钟后,开始对全局变量中的版本分配随机延迟时间和初始化检查时间(注意这个随机延迟时间是逐渐增大,以保证后续每次执行周期内只对一个代码执行检查更新,并在默认 3 小时内检查一遍所有的代码版本)。
4 然后设置定时器,每 x 时间检查一次,这个 x 是根据总间隔时间/总脚本数计算出来的,然后根据延迟时间和上次扫描时间,判断某个代码片段是否需要检查更新。
5 需要更新时会拉取远程代码文件,并解析出版本信息,如果需要更新则更新全局变量里的版本信息,并更新本次检查时间。
6 然后,当你打开思源代码片段窗口时,会读取全局变量中的版本信息,发现有新版本的代码则显示到代码片段窗口的顶部。
7 然后,如果你对某个更新的片段感兴趣,可以进去查看更新信息。

常见问题

协议规则必须遵守吗?

是的,但协议有一定的容错性,比如大小写问题,甚至支持 name: xxxx 这样的格式,但建议按上述标准填写,以免出现意外。

未遵循协议会怎样?多个重复的注释内容,以哪个为准?

未遵循协议的代码片段会被忽略,多个重复的注释内容,以第一个为准(但必须出现在前 200 行以内的,前 200 行以外的会被忽略)。

未使用该协议的代码片段会检查吗?

不会,未使用该协议的代码片段不会检查更新。

支持 css 代码片段吗?

支持。

会自动更新代码吗?

目前不会自动更新,仅仅提示有新版本,需要用户自行查看后,手动更新过来。(因为代码片段中可能有用户自定义的配置等,如果盲目更新覆盖,会导致用户自定义配置丢失)

性能如何?每次刷新时都检查吗?

没有性能问题,刷新时不会检查更新,是定时检查更新,默认每 3 小时检查一遍所有代码片段。

更新的原理是,在页面加载 1 分钟后,会扫描所有遵循上述协议的 js 代码片段,然后把该代码的版本信息存放到 window.snippetsNewVersions.versionList 中(因此也可以通过查看这个变量中的数据,查看目前遵循上述协议的各代码片段的版本信息)。

然后 2 分钟后会产生一个定时器,这个定时器默认是 x 时间扫描一次全局变量中的所有待检查更新的代码片段,当发现有进入需要检查更新的代码片段时,才会去检查更新。这个 x 是根据总时间(默认 3 小时)/总代码片段数计算得来的。

在定时器执行之前,会随机为每个代码片段分配一个随机延迟时间,延迟时间是递增关系,以保证 3 个小时内,每个代码片段都会被检查一次。

这样设计,会把每个代码检查更新的时间随机分散到 3 个小时内,很好的解决了集中检查带来的性能问题。

可以改变检查时间吗?检查时间低于 1 小时的情况怎样设置?

对开发者而言不能,对用户而言,可以通过 interval 参数修改或执行 window.snippetsNewVersions.setInterval(小时数)改变间隔时间,单位是小时。

低于 1 小时的,可以设置为小数,比如,半小时,可设置为 0.5 或 20/60,20 分钟等。

新添加的代码片段遵循了上述协议会检查更新吗?

新添加的代码片段不会检查更新,必须刷新下页面才行(或者说下一次刷新时生效)。因为该代码仅在刷新时扫描所有代码片段,并加入到持续检查队列,因此新添加的代码片段不会被加入到检查队列,但刷新页面后,会重新扫描代码片段,这时新加入的代码片段就会加入到检查队列了。

我是用户,我必须安装用户端代码片段吗?

不是必须,但如果开发者仅遵循了协议,没有加入开发者端代码,而你又没有安装用户端代码,这时并不能提示新版本的。

即用户端和开发者端必须安装一个才行。

如果仅安装了开发者端,开发者端会自动拉取用户端代码。

实际起作用检查更新的还是用户端代码。

总结:在开发者遵循协议的前提下,用户端和开发者端至少安装一个。

我是开发者,我必须让用户安装用户端代码片段吗?

不用要求用户安装用户端代码,只要你遵循协议且加入了开发者端代码即可(具体可参照上一个问题)。

如果用户端和开发者端同时安装且多个开发者都加入了开发者端代码,它们之间会产生冲突吗?

不会产生冲突,开发者端会检查用户是否已安装用户端代码,如果已安装不会重复安装。

多个开发者端也不会产生冲突,在多个开发者端同时运行时,会竞争运行权,最后只有一个运行成功,其他自动退出。

且开发者端在安装和运行用户端前也会检查用户端的安装状态和运行状态,因此也不会重复安装和重复运行。

看起来很多代码运行的样子,会耗资源吗?

不会,并没有很多代码运行,反而非常轻量级。

产生这样的误解,是因为上面介绍里有用户端,开发者端,扫描,检查等概念,给人以同时会很多代码运行的样子。

事实上并不是,如果已安装了用户端,所有开发者端都已经退出了;如果未安装用户端,只有一个开发者端会拉取用户端代码,并下载到本地,然后启动用户端代码,然后就退出了。

所以,最终运行的只有用户端,且用户端运行后并不会立即执行,而是等待 1 分钟时间,因为这时候很可能在页面加载阶段,因此为了不抢占资源,也为了等待所有代码片段加载完毕,因此不会立刻执行。

然后,1 分钟后才会扫描所有代码片段,且扫描期间,每扫描一个会暂停 100 毫秒,也是为了不抢占计算资源,可见,代码设计的每时每刻都在考虑性能问题。然后,扫描完代码片段后,扫描程序就退出了。

再然后,2 分钟后,开始启动初始化版本信息程序,目的是给每个版本增加延迟时间,为了接下来 3 个小时内检查完所有遵循协议的代码更新做准备工作,准备完成后该程序也退出了,这个程序仅内存操作,非常轻量级。

再然后,根据前面的准备工作,启动定时器,定时器会在指定时间间隔内检查队列中进入待检查周期的代码(根据前面的准备数据可知,通常只有一个代码会进入待检查周期),并拉取新版信息,更新队列中的新版信息状态,然后又进入休眠状态,直到下一个定时周期的到来。

可见,整个流程始终都只有一个程序运行,且只要可能涉及耗资源的操作都会周期执行以及把性能消耗分摊掉,或者以时间或者以空间的方式分散开。

所以,整体上,这个代码非常轻量级,且检查更新工作本身也不是 cpu 密集型工作,所以不用担心性能问题。

每个代码片段都会被公平的检查吗?会不会出现某些代码总是优先被检查的情况?

是的,会公平的被检查,不会出现某些脚本被优待的情况。

首先,在分配延迟时间时是随机分配的,保证了公平性。

其次,就算某个代码幸运的分配到了较早时间内被检查,那么仅第一次被优先,之后就会每隔 3 小时之后检查一次,大家就又都公平了。

再者,如果用户刷新了页面,又重新分配随机时间了,不会出现某个脚本一直幸运的情况。

所以,每个代码的检查都是公平公正的 ^_^。

我代码更新后,updateUrl 后面需要加上版本号吗?检查代码会不会拉取不到最新版本?

不需要加版本号,检查代码始终拉取的是最新版本。因为每次拉取时,检查代码都会给每个地址添加最新时间戳参数,保证了拉取的代码一定是最新版本的代码。

后记

目前可能没多少人用 js 代码片段写复杂功能,但可作为备选项,等你需要的时候,提供一种可能。

尤其是通过 cdn 方式,短短几行代码,达到一种神奇的效果,岂不美哉。

注意,这个 cdn 是 jsdelivr 在国内的一些镜像网站,通过自动识别网站的可用性并在最后用 github 和 gitee 做兜底备选方案的方式保证了 cdn 的可用性,不过,如果可能,还是建议把代码直接放到自己的代码片段中更稳定,虽然可能增加一些代码量。

以前可以直接用 jsdelivr 很方便,可惜现在国内无法访问了。

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    28446 引用 • 119786 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    285 引用 • 1986 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 最好不要让用户去发现地址这些找的动作,就放在思源内置里的是最好的。

    我插件系统最开始也是代码片段插入的方法,发布在论坛里,但是效果有限而且问题颇多。后面做了挂件版本,分发和更新都更容易了。

    1 回复
  • 其他回帖
  • 思源 2.x 版本是没有正式版思源插件 ,2.8 之后吧我记得,才开始进行内测。

    在没有思源官方插件集市的时候,思源唯一的注入方式包括代码片段、主题和挂件。因此扩展思源的能力就比较困难,用户群体和开发者群体对于插件系统的呼声也比较高,但是官方那时候主要在弄其他问题(比如数据库),这块一直在往后拖。

    我这面结合自身经验,就先搓了一版社区版 “插件系统”,算是官方插件系统的前身吧。命令面板、插件发布、内置 API、插件技术框架结构在这个版本里都算得上是先驱。在 QQ 群思源折腾群里,也拉上其他的大佬一起开发了一些插件(目录插件、发布插件等一些插件都在旧版插件系统时代就已经发布了)。

    后来思源官方吸纳了这套设计,正式内置了插件系统,这套旧的就没啥用了。不过也为我们发展思源插件留下了宝贵经验。

    最开始是提供的代码片段安装版本,需要自己复制链接添加之类的,容易出错。后来分发使用了挂件(挂件数据重置过,旧时代的挂件没有更新过架构的,就没有在现在的市场里有了),用户使用就方便很多了。

    1 回复
  • zuoez02 1 2 赞同

    作为旧版插件系统的开发者,有一种发明另一个插件系统的感觉,只不过这个插件系统没有提供思源 api。
    参考 https://ld246.com/article/1679498000755

    这篇文章提供了代码片段的一些生态,技术上是很可行的,但是对于代码片段来说我觉得还是挺重的。如果编写代码片段的人都做到上传代码,分发 CDN 这些了,为啥不鼓励他们直接发布到插件市场里呢?

    我觉得你可以直接一步到位,就做个“代码片段大全”的插件,然后搜集一下现在论坛里热门的代码片段整合进去,搞搞宣传,代码片段都搞到你这里做个,以后用代码片段就认准你这个插件,多好trollface

    1 回复
  • wilsons

    好想法耶 👍

    你还别说,这个想法我曾经有过,甚至想过提供一些基础的 api 方便写代码片段,就像你说的,有一种发明另一种插件系统的感觉。

    但之前,我一直陷入一个误区,当时觉得既然是代码片段就应当快速便捷,如果通过 github 等方式发布有些和插件类似了,除非提供在线服务。

    现在经过你的提醒,我突然觉得,不用这么麻烦,只需要用户提供一个网址,遵循基础协议即可。

    这样既解决了存储问题,又达到了快速便捷的效果。

  • 查看全部回帖
wilsons
正式入驻知乎了,以后新贴主要在这里。 欢迎大家订阅关注! 你的关注对我是莫大鼓励,也能让我持续产出优质内容,我们一起成长 🙏 点这里立即关注:https://www.zhihu.com/people/wilsonses