lisonge / vite-plugin-monkey

A vite plugin server and build your.user.js for userscript engine like Tampermonkey, Violentmonkey, Greasemonkey, ScriptCat
MIT License
1.31k stars 70 forks source link

Cannot read properties of undefined (reading '__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED') #70

Closed SSmJaE closed 1 year ago

SSmJaE commented 1 year ago

仅升级vite-plugin-monkey为3.1.1,不修改任何代码、vite配置,出现该报错 https://github.com/SSmJaE/WELearnHelper

似乎和react有关 https://stackoverflow.com/questions/34259664/uncaught-typeerror-cannot-read-property-secret-dom-do-not-use-or-you-will-be

lisonge commented 1 year ago

vite-plugin-monkey@2 使用 inlineDynamicImports=true ,在 vite build 下你的代码所有的 dynamic-import 全部会变成 static-import,此说明在 v2.12.1#dynamic-import

vite-plugin-monkey@3 使用 systemjs 实现单文件下的 dynamic-import

graph LR;
    A(your code)-- vite build -- others plugins -->B(esm)
    B -- vite-plugin-monkey -- vite build library mode --> C{has DynamicImport}
    C -- yes --> D(systemjs)
    C -- no --> E(iife)

因为你在 src/utils/polyfill/index.ts 使用了动态导入,插件使用 systemjs 构建

因为 externalGlobals ,构建出来的代码中有 System.set("user:react", React);

你使用 import React from "react"; 获取 react ,它会被转换为 const React = _import('react').default

但是实际上 React 提供的 cdn 文件导出的 React 模块并没有 default 这个属性,因为 react 直到现在都没有 esm 格式只有 cjs 和 umd

上面的 default 是 undefined , 代码里相当于 default.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 就会产生你看见的错误


这是一个 bug,我将 System.set("user:react", React); 改进一下就行

你想快速解决也很简单,去掉动态导入,因为 vite-plugin-monkey@2 使用 export const GM_xxx = monkeyWindow.GM_xxx 暴露 GM_api

由于 https://github.com/Tampermonkey/tampermonkey/issues/1567 因此 vite-plugin-monkey@3 进一步在 vite build 下将 vite-plugin-monkey/dist/client 重定向至 vite-plugin-monkey/dist/native

https://github.com/lisonge/vite-plugin-monkey/blob/bcc572d3db9ec49e2927436b2cd69efc6c105483/packages/vite-plugin-monkey/src/native/alias.ts#L1-L90

所以静态使用 GM_api 根本不会报 Uncaught ReferenceError: xxx is not defined 错误,你在 src/utils/polyfill/index.ts#L4-L6 实际上没必要用动态导入

或者将 externalGlobals 改成

externalGlobals: {
    react: cdn.jsdelivr("(React.default=React,React)", "umd/react.production.min.js"),
    "react-dom": cdn.jsdelivr("(ReactDOM.default=ReactDOM,ReactDOM)", "umd/react-dom.production.min.js"),
},

也行

lisonge commented 1 year ago

fixed in v3.1.3