From 65547d6bb3e1013fe72526225c5562458c558e4d Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 1 Jun 2026 20:56:11 +0900 Subject: [PATCH] refactor(browser): use `@vitest/ui` package for orchestrator UI assets (#10482) Co-authored-by: Codex --- packages/browser/package.json | 1 + packages/browser/src/client/vite.config.ts | 55 ---------------------- packages/browser/src/node/plugin.ts | 3 +- packages/browser/src/node/projectParent.ts | 3 +- packages/ui/node/index.ts | 7 +-- pnpm-lock.yaml | 3 ++ 6 files changed, 12 insertions(+), 60 deletions(-) diff --git a/packages/browser/package.json b/packages/browser/package.json index 03143c361..d61fcdebb 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -78,6 +78,7 @@ "dependencies": { "@blazediff/core": "1.9.1", "@vitest/mocker": "workspace:*", + "@vitest/ui": "workspace:*", "@vitest/utils": "workspace:*", "magic-string": "catalog:", "pngjs": "^7.0.0", diff --git a/packages/browser/src/client/vite.config.ts b/packages/browser/src/client/vite.config.ts index 95c64a690..263e809b3 100644 --- a/packages/browser/src/client/vite.config.ts +++ b/packages/browser/src/client/vite.config.ts @@ -1,7 +1,4 @@ -import fs from 'node:fs' -import { fileURLToPath } from 'node:url' import { resolve } from 'pathe' -import { globSync } from 'tinyglobby' import * as vite from 'vite' const browserTargets = ['chrome87', 'firefox78', 'safari15.4', 'edge88'] @@ -40,56 +37,4 @@ export default vite.defineConfig({ ], }, }, - plugins: [ - { - name: 'copy-ui-plugin', - - closeBundle: async () => { - const root = resolve( - fileURLToPath(import.meta.url), - '../../../../../packages', - ) - - const ui = resolve(root, 'ui/dist/client') - const uiEntryPoint = resolve(ui, 'index.html') - const browser = resolve(root, 'browser/dist/client/__vitest__/') - - const timeout = setTimeout( - () => console.log('[copy-ui-plugin] Waiting for UI to be built...'), - 1000, - ) - await waitFor(() => fs.existsSync(ui) && fs.existsSync(uiEntryPoint)) - clearTimeout(timeout) - - const files = globSync(['**/*'], { cwd: ui, expandDirectories: false }) - - if (fs.existsSync(browser)) { - fs.rmSync(browser, { recursive: true }) - } - - fs.mkdirSync(browser, { recursive: true }) - fs.mkdirSync(resolve(browser, 'assets')) - - files.forEach((f) => { - fs.copyFileSync(resolve(ui, f), resolve(browser, f)) - }) - - console.log('[copy-ui-plugin] UI copied') - }, - }, - ], }) - -async function waitFor(method: () => boolean, retries = 100): Promise { - if (method()) { - return - } - - if (retries === 0) { - throw new Error('Timeout in waitFor') - } - - await new Promise(resolve => setTimeout(resolve, 500)) - - return waitFor(method, retries - 1) -} diff --git a/packages/browser/src/node/plugin.ts b/packages/browser/src/node/plugin.ts index ff8951770..b675e16be 100644 --- a/packages/browser/src/node/plugin.ts +++ b/packages/browser/src/node/plugin.ts @@ -4,6 +4,7 @@ import type { ParentBrowserProject } from './projectParent' import { createReadStream, readFileSync } from 'node:fs' import { createRequire } from 'node:module' import { dynamicImportPlugin } from '@vitest/mocker/node' +import { distClientRoot as uiClientRoot } from '@vitest/ui' import { toArray } from '@vitest/utils/helpers' import MagicString from 'magic-string' import { dirname, join, resolve } from 'pathe' @@ -345,7 +346,7 @@ export default (parentServer: ParentBrowserProject, base = '/'): Plugin[] => { configureServer(server) { server.middlewares.use( '/__vitest__', - sirv(resolve(distRoot, 'client/__vitest__')), + sirv(uiClientRoot), ) }, resolveId(id) { diff --git a/packages/browser/src/node/projectParent.ts b/packages/browser/src/node/projectParent.ts index c4bcc91fb..2eaab4f37 100644 --- a/packages/browser/src/node/projectParent.ts +++ b/packages/browser/src/node/projectParent.ts @@ -12,6 +12,7 @@ import type { } from 'vitest/node' import type { BrowserServerState } from './state' import { readFile } from 'node:fs/promises' +import { distClientRoot as uiClientRoot } from '@vitest/ui' import { parseErrorStacktrace, parseStacktrace } from '@vitest/utils/source-map' import { extractSourcemapFromFile } from '@vitest/utils/source-map/node' import { join, resolve } from 'pathe' @@ -119,7 +120,7 @@ export class ParentBrowserProject { })().then(manifest => (this.manifest = manifest)) this.orchestratorHtml = (project.config.browser.ui - ? readFile(resolve(distRoot, 'client/__vitest__/index.html'), 'utf8') + ? readFile(resolve(uiClientRoot, 'index.html'), 'utf8') : readFile(resolve(distRoot, 'client/orchestrator.html'), 'utf8')) .then(html => (this.orchestratorHtml = html)) this.injectorJs = readFile( diff --git a/packages/ui/node/index.ts b/packages/ui/node/index.ts index 71563eae5..ac849e50a 100644 --- a/packages/ui/node/index.ts +++ b/packages/ui/node/index.ts @@ -7,6 +7,8 @@ import c from 'tinyrainbow' import { isFileServingAllowed, isValidApiRequest } from 'vitest/node' import { version } from '../package.json' +export const distClientRoot: string = resolve(fileURLToPath(import.meta.url), '../client') + export default (ctx: Vitest): Vite.Plugin => { if (ctx.version !== version) { ctx.logger.warn( @@ -45,8 +47,7 @@ export default (ctx: Vitest): Vite.Plugin => { ) } - const clientDist = resolve(fileURLToPath(import.meta.url), '../client') - const clientIndexHtml = fs.readFileSync(resolve(clientDist, 'index.html'), 'utf-8') + const clientIndexHtml = fs.readFileSync(resolve(distClientRoot, 'index.html'), 'utf-8') // eslint-disable-next-line prefer-arrow-callback server.middlewares.use(function vitestAttachment(req, res, next) { @@ -109,7 +110,7 @@ export default (ctx: Vitest): Vite.Plugin => { server.middlewares.use( base, - sirv(clientDist, { + sirv(distClientRoot, { single: true, dev: true, }), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97e5a96db..add6fdc6b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -526,6 +526,9 @@ importers: '@vitest/mocker': specifier: workspace:* version: link:../mocker + '@vitest/ui': + specifier: workspace:* + version: link:../ui '@vitest/utils': specifier: workspace:* version: link:../utils -- 2.51.2