fix(MaxKB): 「启用 MaxKB」开关在生产构建下拦不住脚本

vite 的 inject-maxkb 插件把 `<script src>` 写进 index.html 的 head,于是构建
产物在 Vue 启动之前就把第三方挂件拉下来执行了。App.vue 的 useMaxKB() 那条运行时
路径只能事后把标签和 `[id^="maxkb-"]` 的 DOM 删掉 —— 代码早跑完了。表现就是后台
把开关关掉、刷新,挂件的副作用照旧(其中之一是它自带的性能上报在每个页面抛
`Cannot read properties of undefined (reading 'startTime')`,堆栈全是 <anonymous>
因为它 bootstrap 时又 eval 了一层),而且关不掉。

改成只留运行时那一条路:

- 删掉 inject-maxkb 插件,index.html 不再带这个 script 标签。原地留注释说明
  为什么不能加回去。
- config store 的 enableMaxkb 默认值从 true 改成 false。默认 true 的话
  getConfig() 还没回来挂件就已经加载了,服务端说「关」依然晚一步。代价是配置
  拿不到时挂件不出现 —— 第三方脚本 fail closed 是对的方向。
- URL 为空的兜底从 vite 插件挪进 loadMaxKBScript,否则会拿 undefined 当 src。

验证:headless chromium 走 CDP 记录网络请求。

- dev(5173):enable_maxkb=false → 0 个请求、0 个 script 标签;改成 true →
  发出 embed 请求、head 里 1 个标签。
- 生产构建(bun run build 后把 dist 静态跑起来、/api 转发到后端):同样两种
  配置下分别是 0 和 1。构建出来的 index.html 里已经没有 maxkb 的 script 标签,
  只剩原本就在源文件里的那行 maxkbMaskTip。

MaxKB 脚本自身那个 startTime 报错是它自己的 bug,本次只保证「关得掉」,没去
动第三方代码。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 00:26:54 -06:00
parent d3757954cd
commit 8600f8143a
3 changed files with 19 additions and 22 deletions

View File

@@ -43,6 +43,11 @@ export function useMaxKB() {
if (!enableMaxkb) {
return
}
// 没配地址就什么都不做。这道判断原来在 vite 的 inject-maxkb 插件里,
// 插件删掉之后得挪过来,否则会拿 undefined 当 src 去请求一个 /undefined
if (!import.meta.env.PUBLIC_MAXKB_URL) {
return
}
const existingScript = document.querySelector(
`script[src="${import.meta.env.PUBLIC_MAXKB_URL}"]`,

View File

@@ -10,7 +10,10 @@ export const useConfigStore = defineStore("config", () => {
submissionListShowAll: true,
allowRegister: false,
classList: [],
enableMaxkb: true,
// 默认 false这是给 useMaxKB 用的开关,而 MaxKB 是第三方脚本。
// 默认 true 的话getConfig() 还没回来挂件就已经加载执行了,服务端配置说
// 「关」也只能事后删标签,等于开关失效。宁可晚一个来回出现,也不要关不掉。
enableMaxkb: false,
})
async function getConfig() {
const res = await getWebsiteConfig()

View File

@@ -1,5 +1,5 @@
import { fileURLToPath, URL } from "node:url"
import { defineConfig, loadEnv, type Plugin } from "vite"
import { defineConfig, loadEnv } from "vite"
import vue from "@vitejs/plugin-vue"
import legacy from "@vitejs/plugin-legacy"
import AutoImport from "unplugin-auto-import/vite"
@@ -69,25 +69,15 @@ const polyfills = [
"web.url.can-parse",
]
// index.html 里按需注入 MaxKB 脚本(原 Rsbuild EJS 模板的等价实现)
function injectMaxkb(maxkbUrl: string | undefined): Plugin {
return {
name: "inject-maxkb",
transformIndexHtml(html) {
if (!maxkbUrl) return html
return {
html,
tags: [
{
tag: "script",
attrs: { async: true, defer: true, src: maxkbUrl },
injectTo: "head",
},
],
}
},
}
}
// MaxKB 脚本**不要**在这里注入 index.html。
//
// 原来有个 inject-maxkb 插件把 <script src> 写进 head于是构建产物在 Vue 启动之前
// 就把挂件拉下来执行了 —— 后台那个「启用 MaxKB」开关根本拦不住它关掉也只是
// 事后把标签和 DOM 删掉代码早跑完了表现之一MaxKB 自带的性能上报在每个页面
// 抛 `Cannot read properties of undefined (reading 'startTime')`,且关不掉)。
//
// 现在只走运行时那一条路App.vue 的 useMaxKB() 等站点配置回来,
// enableMaxkb 为真才建 script 标签。
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), "PUBLIC_")
@@ -144,7 +134,6 @@ export default defineConfig(({ mode }) => {
resolvers: [NaiveUiResolver()],
dts: "./src/components.d.ts",
}),
injectMaxkb(env["PUBLIC_MAXKB_URL"]),
],
envPrefix: "PUBLIC_",
resolve: {