From 299a893ac5e653b9df059cbe221c040f5ba6f126 Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Fri, 6 Mar 2026 17:01:18 +0800 Subject: [PATCH] chore: bring back code-inspector-plugin and agentation (#33088) Co-authored-by: zhsama --- web/app/layout.tsx | 6 +- web/next.config.ts | 6 ++ web/package.json | 2 + web/plugins/vite/code-inspector.ts | 71 +++++++++++++++ web/pnpm-lock.yaml | 136 +++++++++++++++++++++++++++++ web/vite.config.ts | 17 ++-- 6 files changed, 231 insertions(+), 7 deletions(-) create mode 100644 web/plugins/vite/code-inspector.ts diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 44af079eea..addd5c2d5a 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -1,8 +1,10 @@ import type { Viewport } from 'next' +import { Agentation } from 'agentation' import { Provider as JotaiProvider } from 'jotai' import { ThemeProvider } from 'next-themes' import { Instrument_Serif } from 'next/font/google' import { NuqsAdapter } from 'nuqs/adapters/next/app' +import { IS_DEV } from '@/config' import GlobalPublicStoreProvider from '@/context/global-public-context' import { TanstackQueryInitializer } from '@/context/query-client' import { getDatasetMap } from '@/env' @@ -11,7 +13,6 @@ import { cn } from '@/utils/classnames' import { ToastProvider } from './components/base/toast' import { TooltipProvider } from './components/base/ui/tooltip' import BrowserInitializer from './components/browser-initializer' -import { ReactGrabLoader } from './components/devtools/react-grab/loader' import { ReactScanLoader } from './components/devtools/react-scan/loader' import { I18nServerProvider } from './components/provider/i18n-server' import SentryInitializer from './components/sentry-initializer' @@ -57,7 +58,7 @@ const LocaleLayout = async ({ - + {/* */} + {IS_DEV && } diff --git a/web/next.config.ts b/web/next.config.ts index 3c726c96f1..e4c6663999 100644 --- a/web/next.config.ts +++ b/web/next.config.ts @@ -1,5 +1,6 @@ import type { NextConfig } from 'next' import createMDX from '@next/mdx' +import { codeInspectorPlugin } from 'code-inspector-plugin' import { env } from './env' const isDev = process.env.NODE_ENV === 'development' @@ -14,6 +15,11 @@ const remoteImageURLs = ([hasSetWebPrefix ? new URL(`${env.NEXT_PUBLIC_WEB_PREFI const nextConfig: NextConfig = { basePath: env.NEXT_PUBLIC_BASE_PATH, transpilePackages: ['@t3-oss/env-core', '@t3-oss/env-nextjs', 'echarts', 'zrender'], + turbopack: { + rules: codeInspectorPlugin({ + bundler: 'turbopack', + }), + }, productionBrowserSourceMaps: false, // enable browser source map generation during the production build // Configure pageExtensions to include md and mdx pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'], diff --git a/web/package.json b/web/package.json index 934f9c2995..61e39a5bbd 100644 --- a/web/package.json +++ b/web/package.json @@ -216,7 +216,9 @@ "@vitejs/plugin-react": "5.1.4", "@vitejs/plugin-rsc": "0.5.21", "@vitest/coverage-v8": "4.0.18", + "agentation": "2.2.1", "autoprefixer": "10.4.21", + "code-inspector-plugin": "1.4.2", "cross-env": "10.1.0", "eslint": "10.0.2", "eslint-plugin-better-tailwindcss": "https://pkg.pr.new/hyoban/eslint-plugin-better-tailwindcss@a520d15", diff --git a/web/plugins/vite/code-inspector.ts b/web/plugins/vite/code-inspector.ts new file mode 100644 index 0000000000..fe5e3ee769 --- /dev/null +++ b/web/plugins/vite/code-inspector.ts @@ -0,0 +1,71 @@ +import type { Plugin } from 'vite' +import fs from 'node:fs' +import path from 'node:path' +import { codeInspectorPlugin } from 'code-inspector-plugin' +import { injectClientSnippet, normalizeViteModuleId } from './utils' + +type CodeInspectorPluginOptions = { + injectTarget: string + port?: number +} + +type ForceInspectorClientInjectionPluginOptions = CodeInspectorPluginOptions & { + projectRoot: string +} + +export const createCodeInspectorPlugin = ({ + injectTarget, + port = 5678, +}: CodeInspectorPluginOptions): Plugin => { + return codeInspectorPlugin({ + bundler: 'vite', + port, + injectTo: injectTarget, + exclude: [/^(?!.*\.(?:js|ts|mjs|mts|jsx|tsx|vue|svelte|html)(?:$|\?)).*/], + }) as Plugin +} + +const getInspectorRuntimeSnippet = (runtimeFile: string): string => { + if (!fs.existsSync(runtimeFile)) + return '' + + const raw = fs.readFileSync(runtimeFile, 'utf-8') + + // Strip the helper component default export to avoid duplicate default exports after injection. + return raw.replace( + /\s*export default function CodeInspectorEmptyElement\(\)\s*\{[\s\S]*$/, + '', + ) +} + +export const createForceInspectorClientInjectionPlugin = ({ + injectTarget, + port = 5678, + projectRoot, +}: ForceInspectorClientInjectionPluginOptions): Plugin => { + const runtimeFile = path.resolve( + projectRoot, + `node_modules/code-inspector-plugin/dist/append-code-${port}.js`, + ) + const clientSnippet = getInspectorRuntimeSnippet(runtimeFile) + + return { + name: 'vinext-force-code-inspector-client', + apply: 'serve', + enforce: 'pre', + transform(code, id) { + if (!clientSnippet) + return null + + const cleanId = normalizeViteModuleId(id) + if (cleanId !== injectTarget) + return null + + const nextCode = injectClientSnippet(code, 'code-inspector-component', clientSnippet) + if (nextCode === code) + return null + + return { code: nextCode, map: null } + }, + } +} diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 0308a68d2d..7fe3ec13a4 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -514,9 +514,15 @@ importers: '@vitest/coverage-v8': specifier: 4.0.18 version: 4.0.18(vitest@4.0.18(@types/node@24.10.12)(jiti@1.21.7)(jsdom@27.3.0(canvas@3.2.1))(lightningcss@1.31.1)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + agentation: + specifier: 2.2.1 + version: 2.2.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) autoprefixer: specifier: 10.4.21 version: 10.4.21(postcss@8.5.6) + code-inspector-plugin: + specifier: 1.4.2 + version: 1.4.2 cross-env: specifier: 10.1.0 version: 10.1.0 @@ -949,6 +955,24 @@ packages: '@clack/prompts@1.0.1': resolution: {integrity: sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q==} + '@code-inspector/core@1.4.2': + resolution: {integrity: sha512-7OPkFtkfYaXhuTlwub2jT++rW7VggMMEeqsPIZGvHdXykwKAtzB8nnrj3N3uBT/mRoFfP627ShrVyRzCqyfr2w==} + + '@code-inspector/esbuild@1.4.2': + resolution: {integrity: sha512-VouLJBEu82j7XcGHMPBt/VGt+bnA6JeWOMteFyj7buFbGs/ged2WlfUKUMOOx1ILoSn80Fb2EZ8MfSCrEFxnUQ==} + + '@code-inspector/mako@1.4.2': + resolution: {integrity: sha512-0SGR4QruaMCkly/eqMYy+LR06pzyuQnGolrmgWgwGEm0pXs4XuT0lWoX/3zVUvUujmvj7Y/uN2mX1+yMfuORDw==} + + '@code-inspector/turbopack@1.4.2': + resolution: {integrity: sha512-nT59NCsGaJ7vscJ8usQtzpREffMKfcyZnN2q9exJGwlFpq0KOLXFhvwWhMid56rF3LqP43Yj3ib+tE3fxbpzCQ==} + + '@code-inspector/vite@1.4.2': + resolution: {integrity: sha512-wNshKosjULPpiFwU7KPpLnt/8gdcNnd5hyIdkKPpcNc7E6mk432U1g119PXL5cKtjhWk53jce6tuxExhDqZLVQ==} + + '@code-inspector/webpack@1.4.2': + resolution: {integrity: sha512-edSygDoOUyBHI4LLMwmscLdSgg1+1E6OlG1T//NafaHw1eNyduAdRlNXpMPTJlbPYCglzvxus1yCab4WPWjqqQ==} + '@csstools/color-helpers@5.1.0': resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} engines: {node: '>=18'} @@ -3681,6 +3705,17 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + agentation@2.2.1: + resolution: {integrity: sha512-yV9P1DggI7M3SRaRwLwt+xqE5lXqg5l8xtqCr8KzEkbnH8Wa6eRATU97uKnD7cC8FrsJP62Mmw0Xf5Xi5KV50Q==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + ahooks@3.9.5: resolution: {integrity: sha512-TrjXie49Q8HuHKTa84Fm9A+famMDAG1+7a9S9Gq6RQ0h90Jgqmiq3CkObuRjWT/C4d6nRZCw35Y2k2fmybb5eA==} engines: {node: '>=18'} @@ -3781,6 +3816,9 @@ packages: resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + autoprefixer@10.4.21: resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} engines: {node: ^10 || ^12 || >=14} @@ -3904,6 +3942,10 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + chalk@4.1.1: + resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==} + engines: {node: '>=10'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -4028,6 +4070,9 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc + code-inspector-plugin@1.4.2: + resolution: {integrity: sha512-vkrzXbCskYonLd1cLQNdmOOPE2ePThdnHjmrviQ/jAE6E1+ShpRE8clrLp1mvfcT0a/WyMVCW2gC1nAd8XPlZg==} + collapse-white-space@2.1.0: resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} @@ -4443,6 +4488,10 @@ packages: domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + echarts-for-react@3.0.5: resolution: {integrity: sha512-YpEI5Ty7O/2nvCfQ7ybNa+S90DwE8KYZWacGvJW4luUqywP7qStQ+pxDlYOmr4jGDu10mhEkiAuMKcUlT4W5vg==} peerDependencies: @@ -5574,6 +5623,9 @@ packages: resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} engines: {node: '>=16.0.0'} + launch-ide@1.4.0: + resolution: {integrity: sha512-c2mcqZy7mNhzXiWoBFV0lDsEOfpSFGqqxKubPffhqcnv3GV0xpeGcHWLxYFm+jz1/5VAKp796QkyVV4++07eiw==} + layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} @@ -6349,6 +6401,10 @@ packages: points-on-path@0.2.1: resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + portfinder@1.0.38: + resolution: {integrity: sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==} + engines: {node: '>= 10.12'} + postcss-import@15.1.0: resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} @@ -8378,6 +8434,48 @@ snapshots: picocolors: 1.1.1 sisteransi: 1.0.5 + '@code-inspector/core@1.4.2': + dependencies: + '@vue/compiler-dom': 3.5.27 + chalk: 4.1.2 + dotenv: 16.6.1 + launch-ide: 1.4.0 + portfinder: 1.0.38 + transitivePeerDependencies: + - supports-color + + '@code-inspector/esbuild@1.4.2': + dependencies: + '@code-inspector/core': 1.4.2 + transitivePeerDependencies: + - supports-color + + '@code-inspector/mako@1.4.2': + dependencies: + '@code-inspector/core': 1.4.2 + transitivePeerDependencies: + - supports-color + + '@code-inspector/turbopack@1.4.2': + dependencies: + '@code-inspector/core': 1.4.2 + '@code-inspector/webpack': 1.4.2 + transitivePeerDependencies: + - supports-color + + '@code-inspector/vite@1.4.2': + dependencies: + '@code-inspector/core': 1.4.2 + chalk: 4.1.1 + transitivePeerDependencies: + - supports-color + + '@code-inspector/webpack@1.4.2': + dependencies: + '@code-inspector/core': 1.4.2 + transitivePeerDependencies: + - supports-color + '@csstools/color-helpers@5.1.0': {} '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': @@ -11278,6 +11376,11 @@ snapshots: agent-base@7.1.4: {} + agentation@2.2.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + optionalDependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + ahooks@3.9.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@babel/runtime': 7.28.6 @@ -11378,6 +11481,8 @@ snapshots: astring@1.9.0: {} + async@3.2.6: {} + autoprefixer@10.4.21(postcss@8.5.6): dependencies: browserslist: 4.28.1 @@ -11488,6 +11593,11 @@ snapshots: chai@6.2.2: {} + chalk@4.1.1: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -11616,6 +11726,18 @@ snapshots: - '@types/react' - '@types/react-dom' + code-inspector-plugin@1.4.2: + dependencies: + '@code-inspector/core': 1.4.2 + '@code-inspector/esbuild': 1.4.2 + '@code-inspector/mako': 1.4.2 + '@code-inspector/turbopack': 1.4.2 + '@code-inspector/vite': 1.4.2 + '@code-inspector/webpack': 1.4.2 + chalk: 4.1.1 + transitivePeerDependencies: + - supports-color + collapse-white-space@2.1.0: {} color-convert@2.0.1: @@ -12031,6 +12153,8 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 + dotenv@16.6.1: {} + echarts-for-react@3.0.5(echarts@5.6.0)(react@19.2.4): dependencies: echarts: 5.6.0 @@ -13400,6 +13524,11 @@ snapshots: vscode-languageserver-textdocument: 1.0.12 vscode-uri: 3.0.8 + launch-ide@1.4.0: + dependencies: + chalk: 4.1.2 + dotenv: 16.6.1 + layout-base@1.0.2: {} layout-base@2.0.1: {} @@ -14456,6 +14585,13 @@ snapshots: path-data-parser: 0.1.0 points-on-curve: 0.2.0 + portfinder@1.0.38: + dependencies: + async: 3.2.6 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + postcss-import@15.1.0(postcss@8.5.6): dependencies: postcss: 8.5.6 diff --git a/web/vite.config.ts b/web/vite.config.ts index cbe8eb31c9..e898d3fb26 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -5,8 +5,8 @@ import vinext from 'vinext' import { defineConfig } from 'vite' import Inspect from 'vite-plugin-inspect' import tsconfigPaths from 'vite-tsconfig-paths' +import { createCodeInspectorPlugin, createForceInspectorClientInjectionPlugin } from './plugins/vite/code-inspector' import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr' -import { reactGrabOpenFilePlugin } from './plugins/vite/react-grab-open-file' const projectRoot = path.dirname(fileURLToPath(import.meta.url)) const isCI = !!process.env.CI @@ -39,13 +39,20 @@ export default defineConfig(({ mode }) => { ] : [ Inspect(), - react(), - vinext(), - customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }), - reactGrabOpenFilePlugin({ + createCodeInspectorPlugin({ + injectTarget: browserInitializerInjectTarget, + }), + createForceInspectorClientInjectionPlugin({ injectTarget: browserInitializerInjectTarget, projectRoot, }), + react(), + vinext(), + customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }), + // reactGrabOpenFilePlugin({ + // injectTarget: browserInitializerInjectTarget, + // projectRoot, + // }), ], resolve: { alias: {