vite-plugin-monkey初使用

以往我想写一个用户脚本,我会在Tampermonkey提供的编辑页面编写脚本并进行测试。但是这并不方便,例如当我一个脚本拥有许多功能,在开发时将所有代码编于一个文件可并不是一个好的行为:它会导致编辑器卡顿、代码过长而难以定位函数、可读性下降。并且包括Tampermonkey在内的一系列插件并没有提供一个完好的开发环境。 于是我找到了vite-plugin-monkey,它是一个Vite插件。(Vite 是一个新一代的前端构建工具,旨在提供快速的开发体验。)它使我的开发体验好了不少,因为我可以在完整的IDE内进行开发, 并且我能够使用TypeScript语言(TS是JavaScript的超集,提供了一系列更好的功能),享受IDE带来的错误检测、自动补全。更重要的是,我可以将我编写的用户脚本的各个功能写在不同的ts文件当中,这方便了我的开发过程,使我的程序模块化了。这是好的。除此之外,我还可以方便地使用特殊变量及GM函数(GreaseMonkey API),只要这样就行了:

import {unsafeWindow, GM_xmlhttpRequest} from "$";

在我使用插件unplugin-auto-import后,这一切都变得神秘起来。

美中不足的是,他可能并没有一个绝妙的体验。 它提供一个用户脚本,内容如下:

;((entrySrc) => {
  window.GM;
  const key = `__monkeyWindow-` + new URL(entrySrc).origin;
  document[key] = window;
  console.log(`[vite-plugin-monkey] mount monkeyWindow to document`);
  if (typeof GM_addElement === "function") {
    GM_addElement(document.head, "script", {
      type: "module",
      src: entrySrc
    });
  } else {
    const script = document.createElement("script");
    script.type = "module";
    if (window.trustedTypes) {
      const policy = window.trustedTypes.createPolicy(key, {
        createScriptURL: (input) => input
      });
      const trustedScriptURL = policy.createScriptURL(entrySrc);
      script.src = trustedScriptURL;
    } else {
      script.src = entrySrc;
    }
    document.head.append(script);
  }
  console.log(`[vite-plugin-monkey] mount entry module to document.head`);
})("http://127.0.0.1:5173/__vite-plugin-monkey.entry.js");

然而, 受限于浏览器加载策略和诸如CSP一类的东西,__vite-plugin-monkey.entry.js并没有加载进来。这导致我可能需要手动更新脚本,这十分甚至九分地麻烦。 好在,我找到了一种解决方法:使用Violentmonkey,即“暴力猴”,它可以监控外部修改,当检测到外部修改时重新获取用户脚本,当然也可以选择重载页面;当我修改本地文件时,Vite会自动构建新的用户脚本(使用bunx vite build --watch),这有一种HMR(Hot Module Replacement,热模块替换)的美感。即使有时检测外部修改失败了,这对比以前手动加载也方便得多。

题外话,当我尝试监听window.history时出了点问题,不过我发现我只要unsafeWindow.document.querySelector('#app').__vue__.$router.afterHooks.push(<Function>)就可以了。