refactor!: move to module-runner (#1946)

This commit is contained in:
Eli
2025-12-16 10:35:53 -06:00
committed by Aaron
parent c10d09fbdb
commit 4b26d872ec
5 changed files with 71 additions and 61 deletions
Generated
+1 -8
View File
@@ -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=="],
+1 -2
View File
@@ -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": {
+67 -49
View File
@@ -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 {
@@ -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;
+1 -1
View File
@@ -1223,7 +1223,7 @@ export interface WxtBuilder {
* Import a JS entrypoint file, returning the default export containing the
* options.
*/
importEntrypoint<T>(path: string): Promise<T>;
importEntrypoint<T>(this: WxtBuilder, path: string): Promise<T>;
/** Import a list of JS entrypoint files, returning their options. */
importEntrypoints(paths: string[]): Promise<Record<string, unknown>[]>;
/**