From 4b26d872ec36fa55258fe8cb0aeddd721f3b8877 Mon Sep 17 00:00:00 2001 From: Eli <88557639+lishaduck@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:35:53 -0600 Subject: [PATCH] refactor!: move to module-runner (#1946) --- bun.lock | 9 +- packages/wxt/package.json | 3 +- packages/wxt/src/core/builders/vite/index.ts | 116 ++++++++++-------- .../plugins/removeEntrypointMainFunction.ts | 2 +- packages/wxt/src/types.ts | 2 +- 5 files changed, 71 insertions(+), 61 deletions(-) diff --git a/bun.lock b/bun.lock index f710c0b7..253b768d 100644 --- a/bun.lock +++ b/bun.lock @@ -331,7 +331,6 @@ "scule": "^1.3.0", "tinyglobby": "^0.2.16", "unimport": "^3.13.1 || ^4.0.0 || ^5.0.0 || ^6.0.0", - "vite-node": "^3.2.4 || ^5.0.0 || ^6.0.0", "web-ext-run": "^0.2.4", }, "devDependencies": { @@ -357,7 +356,7 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "vite": "^5.4.19 || ^6.3.4 || ^7.0.0 || ^8.0.0-0", + "vite": "^6.3.4 || ^7.0.0 || ^8.0.0-0", }, "optionalPeers": [ "eslint", @@ -2406,8 +2405,6 @@ "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], - "vite-node": ["vite-node@5.3.0", "", { "dependencies": { "cac": "^6.7.14", "es-module-lexer": "^2.0.0", "obug": "^2.1.1", "pathe": "^2.0.3", "vite": "^7.3.1" }, "bin": { "vite-node": "dist/cli.mjs" } }, "sha512-8f20COPYJujc3OKPX6OuyBy3ZIv2det4eRRU4GY1y2MjbeGSUmPjedxg1b72KnTagCofwvZ65ThzjxDW2AtQFQ=="], - "vite-plugin-solid": ["vite-plugin-solid@2.11.10", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-Yr1dQybmtDtDAHkii6hXuc1oVH9CPcS/Zb2jN/P36qqcrkNnVPsMTzQ06jyzFPFjj3U1IYKMVt/9ZqcwGCEbjw=="], "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], @@ -2786,10 +2783,6 @@ "vite/tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - "vite-node/cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], - - "vite-node/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - "vitepress/@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.4", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA=="], "vitepress/shiki": ["shiki@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/langs": "2.5.0", "@shikijs/themes": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ=="], diff --git a/packages/wxt/package.json b/packages/wxt/package.json index 6690e5ef..6e207097 100644 --- a/packages/wxt/package.json +++ b/packages/wxt/package.json @@ -54,12 +54,11 @@ "scule": "^1.3.0", "tinyglobby": "^0.2.16", "unimport": "^3.13.1 || ^4.0.0 || ^5.0.0 || ^6.0.0", - "vite-node": "^3.2.4 || ^5.0.0 || ^6.0.0", "web-ext-run": "^0.2.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "vite": "^5.4.19 || ^6.3.4 || ^7.0.0 || ^8.0.0-0" + "vite": "^6.3.4 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "eslint": { diff --git a/packages/wxt/src/core/builders/vite/index.ts b/packages/wxt/src/core/builders/vite/index.ts index 4c6bf383..d5a082e0 100644 --- a/packages/wxt/src/core/builders/vite/index.ts +++ b/packages/wxt/src/core/builders/vite/index.ts @@ -2,9 +2,6 @@ import { Hookable } from 'hookable'; import { mkdir, readdir, rename, rmdir, stat } from 'node:fs/promises'; import { dirname, extname, join, relative, resolve } from 'node:path'; import type * as vite from 'vite'; -import { ViteNodeRunner } from 'vite-node/client'; -import { ViteNodeServer } from 'vite-node/server'; -import { installSourcemapsSupport } from 'vite-node/source-map'; import { BuildStepOutput, Entrypoint, @@ -83,7 +80,6 @@ export async function createViteBuilder( // TODO: Remove once https://github.com/wxt-dev/wxt/pull/1411 is merged config.legacy ??= {}; - // @ts-ignore: Untyped option: config.legacy.skipWebSocketTokenCheck = true; // Solves https://github.com/wxt-dev/wxt/issues/353 @@ -110,8 +106,9 @@ export async function createViteBuilder( wxtPlugins.resolveAppConfig(wxtConfig), ); if ( + // TODO: Should this be migrated to use perEnvironmentState? wxtConfig.analysis.enabled && - // If included, vite-node entrypoint loader will increment the + // If included, entrypoint loader will increment the // bundleAnalysis's internal build index tracker, which we don't want !baseConfigOptions?.excludeAnalysisPlugin ) { @@ -259,8 +256,7 @@ export async function createViteBuilder( }, }; }; - - const createViteNodeImporter = async (paths: string[]) => { + const createImporterEnvironment = async (paths: string[]) => { const baseConfig = await getBaseConfig({ excludeAnalysisPlugin: true, }); @@ -273,30 +269,47 @@ export async function createViteBuilder( wxtPlugins.removeEntrypointMainFunction(wxtConfig, path), ), }; - const config = vite.mergeConfig(baseConfig, envConfig); - const server = await vite.createServer(config); - await server.pluginContainer.buildStart({}); - const node = new ViteNodeServer(server); - installSourcemapsSupport({ - getSourceMap: (source) => node.getSourceMap(source), - }); - const runner = new ViteNodeRunner({ - root: server.config.root, - base: server.config.base, - // when having the server and runner in a different context, - // you will need to handle the communication between them - // and pass to this function - fetchModule(id) { - return node.fetchModule(id); - }, - resolveId(id, importer) { - return node.resolveId(id, importer); + const importerConfig = vite.mergeConfig(baseConfig, envConfig); + + const config = await vite.resolveConfig( + vite.mergeConfig(importerConfig || {}, { + configFile: false, + envDir: false, + cacheDir: process.cwd(), + environments: { + inline: { + consumer: 'server', + dev: { + moduleRunnerTransform: true, + }, + resolve: { + external: true, + mainFields: [], + conditions: ['node'], + }, + }, + }, + } satisfies vite.InlineConfig), + 'serve', + ); + + const environment = vite.createRunnableDevEnvironment('inline', config, { + runnerOptions: { + hmr: { + logger: false, + }, }, + hot: false, }); - return { runner, server }; + await environment.init(); + + return environment; }; - const requireDefaultExport = (path: string, mod: any) => { + function requireDefaultExport( + path: string, + mod: any, + ): asserts mod is { default: unknown } { const relativePath = relative(wxtConfig.root, path); if (mod?.default == null) { const defineFn = relativePath.includes('.content') @@ -309,36 +322,37 @@ export async function createViteBuilder( `${relativePath}: Default export not found, did you forget to call "export default ${defineFn}(...)"?`, ); } - }; + } return { name: 'Vite', version: vite.version, async importEntrypoint(path) { - const env = createExtensionEnvironment(); - const { runner, server } = await createViteNodeImporter([path]); - const res = await env.run(() => runner.executeFile(path)); - await server.close(); - requireDefaultExport(path, res); - return res.default; + const [module] = await this.importEntrypoints([path]); + + return module as any; }, async importEntrypoints(paths) { - const env = createExtensionEnvironment(); - const { runner, server } = await createViteNodeImporter(paths); - const res = await env.run(() => - Promise.all( - paths.map(async (path) => { - const mod = await runner.executeFile(path); - requireDefaultExport(path, mod); - return mod.default; - }), - ), - ); - await server.close(); - return res; + const context = createExtensionEnvironment(); + const environment = await createImporterEnvironment(paths); + + try { + return await context.run( + async () => + await Promise.all( + paths.map(async (path) => { + const module = await environment.runner.import(path); + requireDefaultExport(path, module); + return module.default as any; + }), + ), + ); + } finally { + await environment.close(); + } }, async build(group) { - let entryConfig; + let entryConfig: vite.InlineConfig; if (Array.isArray(group)) entryConfig = getMultiPageConfig(group); else if ( group.type === 'content-script-style' || @@ -347,12 +361,16 @@ export async function createViteBuilder( entryConfig = getCssConfig(group); else entryConfig = getLibModeConfig(group); - const buildConfig = vite.mergeConfig(await getBaseConfig(), entryConfig); + const buildConfig: vite.InlineConfig = vite.mergeConfig( + await getBaseConfig(), + entryConfig, + ); await hooks.callHook( 'vite:build:extendConfig', toArray(group), buildConfig, ); + const result = await vite.build(buildConfig); const chunks = getBuildOutputChunks(result); return { diff --git a/packages/wxt/src/core/builders/vite/plugins/removeEntrypointMainFunction.ts b/packages/wxt/src/core/builders/vite/plugins/removeEntrypointMainFunction.ts index 1aad7af3..acf5533c 100644 --- a/packages/wxt/src/core/builders/vite/plugins/removeEntrypointMainFunction.ts +++ b/packages/wxt/src/core/builders/vite/plugins/removeEntrypointMainFunction.ts @@ -22,7 +22,7 @@ export function removeEntrypointMainFunction( }, handler(code) { const newCode = removeMainFunctionCode(code); - config.logger.debug('vite-node transformed entrypoint', path); + config.logger.debug('transformed entrypoint', path); config.logger.debug(`Original:\n---\n${code}\n---`); config.logger.debug(`Transformed:\n---\n${newCode.code}\n---`); return newCode; diff --git a/packages/wxt/src/types.ts b/packages/wxt/src/types.ts index 09f3bf3c..37b70558 100644 --- a/packages/wxt/src/types.ts +++ b/packages/wxt/src/types.ts @@ -1223,7 +1223,7 @@ export interface WxtBuilder { * Import a JS entrypoint file, returning the default export containing the * options. */ - importEntrypoint(path: string): Promise; + importEntrypoint(this: WxtBuilder, path: string): Promise; /** Import a list of JS entrypoint files, returning their options. */ importEntrypoints(paths: string[]): Promise[]>; /**