chore: Simplify virtual module setup (#581)
This commit is contained in:
+12
-17
@@ -8,6 +8,10 @@ import { consola } from 'consola';
|
||||
import pMap from 'p-map';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import {
|
||||
virtualModuleNames,
|
||||
virtualEntrypointModuleNames,
|
||||
} from '~/core/utils/virtual-modules';
|
||||
|
||||
const spinnerText = 'Building WXT';
|
||||
const spinner = ora(spinnerText).start();
|
||||
@@ -20,12 +24,7 @@ const preset = {
|
||||
dts: true,
|
||||
silent: true,
|
||||
sourcemap: false,
|
||||
external: [
|
||||
'virtual:user-unlisted-script',
|
||||
'virtual:user-content-script-isolated-world',
|
||||
'virtual:user-content-script-main-world',
|
||||
'virtual:user-background',
|
||||
],
|
||||
external: virtualEntrypointModuleNames.map((name) => `virtual:user-${name}`),
|
||||
} satisfies tsup.Options;
|
||||
|
||||
function spinnerPMap(configs: tsup.Options[]) {
|
||||
@@ -74,17 +73,13 @@ const config: tsup.Options[] = [
|
||||
},
|
||||
{
|
||||
...preset,
|
||||
entry: {
|
||||
'virtual/background-entrypoint': 'src/virtual/background-entrypoint.ts',
|
||||
'virtual/content-script-isolated-world-entrypoint':
|
||||
'src/virtual/content-script-isolated-world-entrypoint.ts',
|
||||
'virtual/content-script-main-world-entrypoint':
|
||||
'src/virtual/content-script-main-world-entrypoint.ts',
|
||||
'virtual/mock-browser': 'src/virtual/mock-browser.ts',
|
||||
'virtual/reload-html': 'src/virtual/reload-html.ts',
|
||||
'virtual/unlisted-script-entrypoint':
|
||||
'src/virtual/unlisted-script-entrypoint.ts',
|
||||
},
|
||||
entry: virtualModuleNames.reduce<Record<string, string>>(
|
||||
(acc, moduleName) => {
|
||||
acc[`virtual/${moduleName}`] = `src/virtual/${moduleName}.ts`;
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
),
|
||||
format: ['esm'],
|
||||
splitting: false,
|
||||
dts: false,
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
BuildStepOutput,
|
||||
Entrypoint,
|
||||
ResolvedConfig,
|
||||
VirtualEntrypointType,
|
||||
WxtBuilder,
|
||||
WxtBuilderServer,
|
||||
WxtDevServer,
|
||||
@@ -13,6 +12,10 @@ import {
|
||||
getEntrypointBundlePath,
|
||||
isHtmlEntrypoint,
|
||||
} from '~/core/utils/entrypoints';
|
||||
import {
|
||||
VirtualEntrypointType,
|
||||
VirtualModuleId,
|
||||
} from '~/core/utils/virtual-modules';
|
||||
|
||||
export async function createViteBuilder(
|
||||
wxtConfig: ResolvedConfig,
|
||||
@@ -48,10 +51,7 @@ export async function createViteBuilder(
|
||||
wxtPlugins.download(wxtConfig),
|
||||
wxtPlugins.devHtmlPrerender(wxtConfig, server),
|
||||
wxtPlugins.unimport(wxtConfig),
|
||||
wxtPlugins.virtualEntrypoint('background', wxtConfig),
|
||||
wxtPlugins.virtualEntrypoint('content-script-isolated-world', wxtConfig),
|
||||
wxtPlugins.virtualEntrypoint('content-script-main-world', wxtConfig),
|
||||
wxtPlugins.virtualEntrypoint('unlisted-script', wxtConfig),
|
||||
wxtPlugins.resolveVirtualModules(wxtConfig),
|
||||
wxtPlugins.devServerGlobals(wxtConfig, server),
|
||||
wxtPlugins.tsconfigPaths(wxtConfig),
|
||||
wxtPlugins.noopBackground(),
|
||||
@@ -268,7 +268,10 @@ function getRollupEntry(entrypoint: Entrypoint): string {
|
||||
: 'content-script-isolated-world';
|
||||
break;
|
||||
}
|
||||
return virtualEntrypointType
|
||||
? `virtual:wxt-${virtualEntrypointType}?${entrypoint.inputPath}`
|
||||
: entrypoint.inputPath;
|
||||
|
||||
if (virtualEntrypointType) {
|
||||
const moduleId: VirtualModuleId = `virtual:wxt-${virtualEntrypointType}-entrypoint`;
|
||||
return `${moduleId}?${entrypoint.inputPath}`;
|
||||
}
|
||||
return entrypoint.inputPath;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ export * from './devServerGlobals';
|
||||
export * from './download';
|
||||
export * from './multipageMove';
|
||||
export * from './unimport';
|
||||
export * from './virtualEntrypoint';
|
||||
export * from './resolveVirtualModules';
|
||||
export * from './tsconfigPaths';
|
||||
export * from './noopBackground';
|
||||
export * from './cssEntrypoints';
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Plugin } from 'vite';
|
||||
import { ResolvedConfig } from '~/types';
|
||||
import { normalizePath } from '~/core/utils/paths';
|
||||
import {
|
||||
VirtualModuleId,
|
||||
virtualModuleNames,
|
||||
} from '~/core/utils/virtual-modules';
|
||||
import fs from 'fs-extra';
|
||||
import { resolve } from 'path';
|
||||
|
||||
/**
|
||||
* Resolve all the virtual modules to the `node_modules/wxt/dist/virtual` directory.
|
||||
*/
|
||||
export function resolveVirtualModules(config: ResolvedConfig): Plugin[] {
|
||||
return virtualModuleNames.map((name) => {
|
||||
const virtualId: `${VirtualModuleId}?` = `virtual:wxt-${name}?`;
|
||||
const resolvedVirtualId = '\0' + virtualId;
|
||||
return {
|
||||
name: `wxt:resolve-virtual-${name}`,
|
||||
resolveId(id) {
|
||||
// Id doesn't start with prefix, it looks like this:
|
||||
// /path/to/project/virtual:wxt-background?/path/to/project/entrypoints/background.ts
|
||||
const index = id.indexOf(virtualId);
|
||||
if (index === -1) return;
|
||||
|
||||
const inputPath = normalizePath(id.substring(index + virtualId.length));
|
||||
return resolvedVirtualId + inputPath;
|
||||
},
|
||||
async load(id) {
|
||||
if (!id.startsWith(resolvedVirtualId)) return;
|
||||
|
||||
const inputPath = id.replace(resolvedVirtualId, '');
|
||||
const template = await fs.readFile(
|
||||
resolve(config.wxtModuleDir, `dist/virtual/${name}.js`),
|
||||
'utf-8',
|
||||
);
|
||||
return template.replace(`virtual:user-${name}`, inputPath);
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import { Plugin } from 'vite';
|
||||
import { ResolvedConfig, VirtualEntrypointType } from '~/types';
|
||||
import fs from 'fs-extra';
|
||||
import { resolve } from 'path';
|
||||
import { normalizePath } from '~/core/utils/paths';
|
||||
|
||||
/**
|
||||
* Wraps a user's entrypoint with a vitual version with additional logic.
|
||||
*/
|
||||
export function virtualEntrypoint(
|
||||
type: VirtualEntrypointType,
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
): Plugin {
|
||||
const virtualId = `virtual:wxt-${type}?`;
|
||||
const resolvedVirtualId = `\0${virtualId}`;
|
||||
|
||||
return {
|
||||
name: `wxt:virtual-entrypoint`,
|
||||
resolveId(id) {
|
||||
// Id doesn't start with prefix, it looks like this:
|
||||
// /path/to/project/virtual:background?/path/to/project/entrypoints/background.ts
|
||||
const index = id.indexOf(virtualId);
|
||||
if (index === -1) return;
|
||||
|
||||
const inputPath = normalizePath(id.substring(index + virtualId.length));
|
||||
return resolvedVirtualId + inputPath;
|
||||
},
|
||||
async load(id) {
|
||||
if (!id.startsWith(resolvedVirtualId)) return;
|
||||
|
||||
const inputPath = id.replace(resolvedVirtualId, '');
|
||||
const template = await fs.readFile(
|
||||
resolve(config.wxtModuleDir, `dist/virtual/${type}-entrypoint.js`),
|
||||
'utf-8',
|
||||
);
|
||||
return template.replace(`virtual:user-${type}`, inputPath);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { describe, it } from 'vitest';
|
||||
import {
|
||||
VirtualModuleId,
|
||||
VirtualModuleName,
|
||||
VirtualEntrypointType,
|
||||
VirtualEntrypointModuleName,
|
||||
} from '../virtual-modules';
|
||||
|
||||
describe('Virtual Modules', () => {
|
||||
it('should resolve types to litteral values, not string', () => {
|
||||
// @ts-expect-error
|
||||
const _c: VirtualEntrypointType = '';
|
||||
// @ts-expect-error
|
||||
const _d: VirtualEntrypointModuleName = '';
|
||||
// @ts-expect-error
|
||||
const _b: VirtualModuleName = '';
|
||||
// @ts-expect-error
|
||||
const _a: VirtualModuleId = '';
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
export const virtualEntrypointTypes = [
|
||||
'content-script-main-world' as const,
|
||||
'content-script-isolated-world' as const,
|
||||
'background' as const,
|
||||
'unlisted-script' as const,
|
||||
];
|
||||
export type VirtualEntrypointType = (typeof virtualEntrypointTypes)[0];
|
||||
|
||||
/**
|
||||
* All the names of entrypoint files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
|
||||
*/
|
||||
export const virtualEntrypointModuleNames = virtualEntrypointTypes.map(
|
||||
(name) => `${name}-entrypoint` as const,
|
||||
);
|
||||
/**
|
||||
* Name of entrypoint files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
|
||||
*/
|
||||
export type VirtualEntrypointModuleName =
|
||||
(typeof virtualEntrypointModuleNames)[0];
|
||||
|
||||
/**
|
||||
* All the names of files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
|
||||
*/
|
||||
export const virtualModuleNames = [
|
||||
...virtualEntrypointModuleNames,
|
||||
'mock-browser' as const,
|
||||
'reload-html' as const,
|
||||
];
|
||||
/**
|
||||
* Name of files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
|
||||
*/
|
||||
export type VirtualModuleName = (typeof virtualModuleNames)[0];
|
||||
|
||||
/**
|
||||
* Import alias used for importing a virtual module
|
||||
*/
|
||||
export type VirtualModuleId = `virtual:wxt-${VirtualModuleName}`;
|
||||
@@ -1103,12 +1103,6 @@ export interface ExtensionRunner {
|
||||
closeBrowser(): Promise<void>;
|
||||
}
|
||||
|
||||
export type VirtualEntrypointType =
|
||||
| 'content-script-main-world'
|
||||
| 'content-script-isolated-world'
|
||||
| 'background'
|
||||
| 'unlisted-script';
|
||||
|
||||
export type EslintGlobalsPropValue =
|
||||
| boolean
|
||||
| 'readonly'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import definition from 'virtual:user-background';
|
||||
import definition from 'virtual:user-background-entrypoint';
|
||||
import { setupWebSocket } from './utils/setup-web-socket';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { browser } from 'wxt/browser';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import definition from 'virtual:user-content-script-isolated-world';
|
||||
import definition from 'virtual:user-content-script-isolated-world-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { ContentScriptContext } from 'wxt/client';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import definition from 'virtual:user-content-script-main-world';
|
||||
import definition from 'virtual:user-content-script-main-world-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
|
||||
(async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import definition from 'virtual:user-unlisted-script';
|
||||
import definition from 'virtual:user-unlisted-script-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
|
||||
(async () => {
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
// Types required to make the virtual modules happy.
|
||||
|
||||
declare module 'virtual:user-background' {
|
||||
declare module 'virtual:user-background-entrypoint' {
|
||||
const definition: { main: () => void };
|
||||
export default definition;
|
||||
}
|
||||
|
||||
declare module 'virtual:user-content-script-isolated-world' {
|
||||
declare module 'virtual:user-content-script-isolated-world-entrypoint' {
|
||||
const definition: {
|
||||
main: (
|
||||
ctx: import('wxt/client').ContentScriptContext,
|
||||
@@ -14,12 +14,12 @@ declare module 'virtual:user-content-script-isolated-world' {
|
||||
export default definition;
|
||||
}
|
||||
|
||||
declare module 'virtual:user-content-script-main-world' {
|
||||
declare module 'virtual:user-content-script-main-world-entrypoint' {
|
||||
const definition: { main: () => void | Promise<void> };
|
||||
export default definition;
|
||||
}
|
||||
|
||||
declare module 'virtual:user-unlisted-script' {
|
||||
declare module 'virtual:user-unlisted-script-entrypoint' {
|
||||
const definition: { main: () => void | Promise<void> };
|
||||
export default definition;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user