From ca20a210ea2333e8343d76bcf013ed93b90f0096 Mon Sep 17 00:00:00 2001 From: Aaron Klinker Date: Thu, 20 Jul 2023 10:38:53 -0500 Subject: [PATCH] feat: Include background script in dev mode if user doesn't define one --- .../build/__tests__/findEntrypoints.test.ts | 24 ++++++++++++++--- src/core/build/findEntrypoints.ts | 26 +++++++++++++++---- src/core/utils/getInternalConfig.ts | 1 + src/core/vite-plugins/index.ts | 1 + src/core/vite-plugins/noopBackground.ts | 24 +++++++++++++++++ 5 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 src/core/vite-plugins/noopBackground.ts diff --git a/src/core/build/__tests__/findEntrypoints.test.ts b/src/core/build/__tests__/findEntrypoints.test.ts index 50a7db9b..a9930a1e 100644 --- a/src/core/build/__tests__/findEntrypoints.test.ts +++ b/src/core/build/__tests__/findEntrypoints.test.ts @@ -210,10 +210,10 @@ describe('findEntrypoints', () => { }, ], ])( - 'should find and load content script entrypoint config from %s', + 'should find and load background entrypoint config from %s', async (path, expected) => { - const options: ContentScriptEntrypoint['options'] = { - matches: [''], + const options: BackgroundEntrypoint['options'] = { + type: 'module', }; globMock.mockResolvedValueOnce([path]); importTsFileMock.mockResolvedValue(options); @@ -226,6 +226,24 @@ describe('findEntrypoints', () => { }, ); + it("should include a virtual background script so dev reloading works when there isn't a background entrypoint defined by the user", async () => { + globMock.mockResolvedValueOnce([]); + + const entrypoints = await findEntrypoints({ + ...config, + command: 'serve', + }); + + expect(entrypoints).toHaveLength(1); + expect(entrypoints[0]).toEqual({ + type: 'background', + inputPath: 'virtual:user-background', + name: 'background', + options: {}, + outputDir: config.outDir, + }); + }); + it.each<[string, GenericEntrypoint]>([ // Sandbox [ diff --git a/src/core/build/findEntrypoints.ts b/src/core/build/findEntrypoints.ts index b28ea7a5..7f4469c2 100644 --- a/src/core/build/findEntrypoints.ts +++ b/src/core/build/findEntrypoints.ts @@ -16,9 +16,10 @@ import JSON5 from 'json5'; import { importTsFile } from '../utils/importTsFile'; import glob from 'fast-glob'; import { getEntrypointName } from '../utils/entrypoints'; +import { VIRTUAL_NOOP_BACKGROUND_MODULE_ID } from '../vite-plugins/noopBackground'; /** - * Return entrypoints and their configuration by looking through the + * Return entrypoints and their configuration by looking through the project's files. */ export async function findEntrypoints( config: InternalConfig, @@ -33,6 +34,7 @@ export async function findEntrypoints( const existingNames: Record = {}; const entrypoints: Entrypoint[] = []; + let hasBackground = false; await Promise.all( relativePaths.map(async (relativePath) => { const path = resolve(config.entrypointsDir, relativePath); @@ -63,6 +65,7 @@ export async function findEntrypoints( break; case 'background': entrypoint = await getBackgroundEntrypoint(config, path); + hasBackground = true; break; case 'content-script': entrypoint = await getContentScriptEntrypoint( @@ -95,6 +98,11 @@ export async function findEntrypoints( existingNames[entrypoint.name] = entrypoint; }), ); + if (config.command === 'serve' && !hasBackground) { + entrypoints.push( + await getBackgroundEntrypoint(config, VIRTUAL_NOOP_BACKGROUND_MODULE_ID), + ); + } return entrypoints; } @@ -195,10 +203,17 @@ async function getBackgroundEntrypoint( config: InternalConfig, path: string, ): Promise { - const { main: _, ...options } = - await importTsFile(path, config); - if (options == null) { - throw Error('Background script does not have a default export'); + let options: Omit = {}; + if (path !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) { + const defaultExport = await importTsFile( + path, + config, + ); + if (defaultExport == null) { + throw Error('Background script does not have a default export'); + } + const { main: _, ...moduleOptions } = defaultExport; + options = moduleOptions; } return { type: 'background', @@ -257,6 +272,7 @@ const PATH_GLOB_TO_TYPE_MAP: Record = { 'devtools/index.html': 'devtools', 'background.ts': 'background', + [VIRTUAL_NOOP_BACKGROUND_MODULE_ID]: 'background', 'content.ts?(x)': 'content-script', 'content/index.ts?(x)': 'content-script', diff --git a/src/core/utils/getInternalConfig.ts b/src/core/utils/getInternalConfig.ts index b7624a4c..fbaacb62 100644 --- a/src/core/utils/getInternalConfig.ts +++ b/src/core/utils/getInternalConfig.ts @@ -142,6 +142,7 @@ export async function getInternalConfig( ); finalConfig.vite.plugins.push(plugins.devServerGlobals(finalConfig)); finalConfig.vite.plugins.push(plugins.tsconfigPaths(finalConfig)); + finalConfig.vite.plugins.push(plugins.noopBackground()); finalConfig.vite.define ??= {}; getGlobals(finalConfig).forEach((global) => { diff --git a/src/core/vite-plugins/index.ts b/src/core/vite-plugins/index.ts index 8264ce4b..b134fa1f 100644 --- a/src/core/vite-plugins/index.ts +++ b/src/core/vite-plugins/index.ts @@ -5,3 +5,4 @@ export * from './multipageMove'; export * from './unimport'; export * from './virtualEntrypoint'; export * from './tsconfigPaths'; +export * from './noopBackground'; diff --git a/src/core/vite-plugins/noopBackground.ts b/src/core/vite-plugins/noopBackground.ts new file mode 100644 index 00000000..84fcd79f --- /dev/null +++ b/src/core/vite-plugins/noopBackground.ts @@ -0,0 +1,24 @@ +import { Plugin } from 'vite'; + +/** + * In dev mode, if there's not a background script listed, we need to add one. + * + * This define's a virtual module that is basically just a noop. + */ +export function noopBackground(): Plugin { + const virtualModuleId = VIRTUAL_NOOP_BACKGROUND_MODULE_ID; + const resolvedVirtualModuleId = '\0' + virtualModuleId; + return { + name: 'wxt:noop-background', + resolveId(id) { + if (id === virtualModuleId) return resolvedVirtualModuleId; + }, + load(id) { + if (id === resolvedVirtualModuleId) { + return `import { defineBackground } from 'wxt/client';\nexport default defineBackground(() => void 0)`; + } + }, + }; +} + +export const VIRTUAL_NOOP_BACKGROUND_MODULE_ID = 'virtual:user-background';