lisonge/vite-plugin-monkey

部分依赖在油猴的环境中直接简单地用 @require 引入会产生冲突

bzy-nya opened this issue · 19 comments

例如

// @require      https://unpkg.com/vue@3.2.37//dist/vue.global.prod.js
// @require      https://unpkg.com/element-plus@2.2.9//dist/index.full.js          // element-plus 依赖 vue

vue.js 会导出一个变量 Vue,element 会寻找 this.Vue 当成依赖,但是在油猴的环境中 this 被重定向到了 window 的一个 proxy(@grant none 就会指向空对象),所以就会发生报错说 vue is not found,即使 vue 变量已经在环境中了。

所以能不能提供一个自定义依赖引入的方法呢?

如何提供 自定义依赖引入
动态添加 script 吗?把 cdn 添加到宿主环境会污染 宿主window 属性,如果宿主使用了 cdn ,两个不同版本的 cdn 导出了同样的变量,宿主的 cdn 会被覆盖,或者其他的方法?

@bzy-nya
另一种解决方式是 element-plus 可以使用按需引入,这样也可减少大小

如何提供 自定义依赖引入 ? 动态添加 script 吗?把 cdn 添加到宿主环境会污染 宿主window 属性,如果宿主使用了 cdn ,两个不同版本的 cdn 导出了同样的变量,宿主的 cdn 会被覆盖,或者其他的方法?

用 get + eval 或者 remote import ?

@bzy-nya 另一种解决方式是 element-plus 可以使用按需引入,这样也可减少大小

嗯喵,我去康康

https://github.com/lisonge/create-monkey/blob/820b0ab14f8d37357b39b5f522772845fbecf652/template-react/dist/vite-react-starter.user.js#L7-L8

react-dom 依赖 react,但是它在油猴扩展内正常加载

虽然没有处理好还是会报错,但是在函数之前加上 var process = {env:{NODE_ENV:'production'}};之后它就能正常运行

https://github.com/lisonge/create-monkey/blob/820b0ab14f8d37357b39b5f522772845fbecf652/template-react/dist/vite-react-starter.user.js#L7-L8

react-dom 依赖 react,但是它在油猴扩展内正常加载

因为 vue.js 是直接

var Vue = {
...
}

但是 react.js 里是

factory(global.React = {})  // global = this || self

然后这样的话油猴里 this.Vue 访问不到,但是 this.React 可以访问。

然后 element-plus 在 require 阶段就会报错(虽然咱感觉这个锅得油猴背)。

https://github.com/lisonge/create-monkey/blob/820b0ab14f8d37357b39b5f522772845fbecf652/template-react/dist/vite-react-starter.user.js#L7-L8

react-dom 依赖 react,但是它在油猴扩展内正常加载

虽然没有处理好还是会报错,但是在函数之前加上 var process = {env:{NODE_ENV:'production'}};之后它就能正常运行

fixed -> https://github.com/lisonge/vite-plugin-monkey/blob/v1.1.2/CHANGELOG.md#112

Vue 的 cdn 使用 iife 格式, element-plus 的 cdn 使用 umd 格式,油猴脚本的环境不支持两者混用

解决方式1: 叫他们同时提供 iife 和 umd 的格式,或者像react/react-dom一样统一umd
解决方式2: 自己下载这些库统一编译输出格式,然后通过 // require http://cdn.jsdelivr.net/gh/ 引用自己仓库的文件
解决方式3: 不使用 cdn,尽量按需引入

Vue 的 cdn 使用 iife 格式, element-plus 的 cdn 使用 umd 格式,油猴脚本的环境不支持两者混用

解决方式1: 叫他们同时提供 iife 和 umd 的格式,或者像react/react-dom一样统一umd 解决方式2: 自己下载这些库统一编译输出格式,然后通过 // require http://cdn.jsdelivr.net/gh/ 引用自己仓库的文件 解决方式3: 不使用 cdn,尽量按需引入

嗯嗯,谢谢了喵,这个 bug(or feature) 咱也给 TamperMonkey 那边提了 issues 但是没人回复所以就来这边了qwq

对于方式2,可以直接用现有的 vite 做

// vite.config.ts
import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
    build: {
        lib: {
            name: 'ElementPlus',
            entry: './node_modules/element-plus',
            formats: ['iife'],
        },
        rollupOptions: {
            external: ['vue'],
            output: {
                globals: {
                    vue: 'Vue',
                },
                exports: 'named',
            },
        },
    },
});

can be fixed by manual build library

@bzy-nya

突发奇想找到了一个解决方法,那就是在 库加载之前使用 @require 插入自定义代码

// ==UserScript==
// @name               dev:example
// @namespace          https://github.com/lisonge
// @version            1.0.1
// @require            https://unpkg.com/vue@3.2.37//dist/vue.global.prod.js
// @require            https://raw.githubusercontent.com/lisonge/src/main/js/monkey.js
// @require            https://unpkg.com/element-plus@2.2.9//dist/index.full.js
// ==/UserScript==

// @grant              none // 在此环境下也可行

console.log(`cdn load ok`);

https://raw.githubusercontent.com/lisonge/src/main/js/monkey.js

try{
  this.Vue = this.Vue ?? Vue
}catch{}
try{
  window.Vue = window.Vue ?? Vue
}catch{}
console.log({this:this, window, globalThis});

草,确实可以这样

我会在配置里扩展一下 build.externalGlobalsvalue,让其支持多条 url

可以直接使用 dataurl 无需额外上传 cdn ,Tampermonkey ,Violentmonkey 我已测试过,均可行

{
          vue: cdn.jsdelivr('Vue', 'dist/vue.global.prod.js').concat(
            'data:application/javascript,' +
              encodeURIComponent(
                `;window.Vue=Vue;`,
              ),
          )
        }
bmqy commented

可以直接使用 dataurl 无需额外上传 cdn ,Tampermonkey ,Violentmonkey 我已测试过,均可行

{
          vue: cdn.jsdelivr('Vue', 'dist/vue.global.prod.js').concat(
            'data:application/javascript,' +
              encodeURIComponent(
                `;window.Vue=Vue;`,
              ),
          )
        }

刚刚踩坑,建议加在文档中:https://github.com/lisonge/vite-plugin-monkey/blob/main/README_zh.md#%E6%8E%92%E9%99%A4%E4%BE%9D%E8%B5%96%E7%9A%84-cdn-%E5%B7%A5%E5%85%B7

可以直接使用 dataurl 无需额外上传 cdn ,Tampermonkey ,Violentmonkey 我已测试过,均可行

{
          vue: cdn.jsdelivr('Vue', 'dist/vue.global.prod.js').concat(
            'data:application/javascript,' +
              encodeURIComponent(
                `;window.Vue=Vue;`,
              ),
          )
        }

刚刚踩坑,建议加在文档中:https://github.com/lisonge/vite-plugin-monkey/blob/main/README_zh.md#%E6%8E%92%E9%99%A4%E4%BE%9D%E8%B5%96%E7%9A%84-cdn-%E5%B7%A5%E5%85%B7

通过 @require 加载的 IIFE 和 UMD 混用的问题

bmqy commented

好的,没注意到下面的内容。。