From 190be7f732f0a7d2b5974dd7334209a42e50fb67 Mon Sep 17 00:00:00 2001
From: Patryk Kuniczak
Date: Sun, 3 Aug 2025 15:40:27 +0200
Subject: [PATCH] fix(rolldown-compat): Only apply footer to content and
unlisted scripts via plugin (#1793)
Co-authored-by: Aaron
---
.../wxt/e2e/tests/output-structure.test.ts | 5 +---
packages/wxt/src/core/builders/vite/index.ts | 24 +++++++++----------
.../core/builders/vite/plugins/iifeFooter.ts | 20 ++++++++++++++++
.../src/core/builders/vite/plugins/index.ts | 1 +
.../core/utils/building/build-entrypoints.ts | 2 +-
packages/wxt/src/utils/app-config.ts | 2 +-
6 files changed, 36 insertions(+), 18 deletions(-)
create mode 100644 packages/wxt/src/core/builders/vite/plugins/iifeFooter.ts
diff --git a/packages/wxt/e2e/tests/output-structure.test.ts b/packages/wxt/e2e/tests/output-structure.test.ts
index 4145eaab..4fd96d35 100644
--- a/packages/wxt/e2e/tests/output-structure.test.ts
+++ b/packages/wxt/e2e/tests/output-structure.test.ts
@@ -1,4 +1,4 @@
-import { describe, it, expect } from 'vitest';
+import { describe, expect, it } from 'vitest';
import { TestProject } from '../utils';
describe('Output Directory Structure', () => {
@@ -362,13 +362,11 @@ describe('Output Directory Structure', () => {
function logHello(name) {
console.log(\`Hello \${name}!\`);
}
- background;
const definition = defineBackground({
main() {
logHello("background");
}
});
- background;
function initPlugins() {
}
((_b = (_a = globalThis.browser) == null ? void 0 : _a.runtime) == null ? void 0 : _b.id) ? globalThis.browser : globalThis.chrome;
@@ -397,7 +395,6 @@ describe('Output Directory Structure', () => {
const result$1 = result;
return result$1;
}();
- background;
"
`);
});
diff --git a/packages/wxt/src/core/builders/vite/index.ts b/packages/wxt/src/core/builders/vite/index.ts
index f37f05df..8eb2068a 100644
--- a/packages/wxt/src/core/builders/vite/index.ts
+++ b/packages/wxt/src/core/builders/vite/index.ts
@@ -25,7 +25,7 @@ import { ViteNodeServer } from 'vite-node/server';
import { ViteNodeRunner } from 'vite-node/client';
import { installSourcemapsSupport } from 'vite-node/source-map';
import { createExtensionEnvironment } from '../../utils/environments';
-import { relative, join, extname, dirname } from 'node:path';
+import { dirname, extname, join, relative } from 'node:path';
import fs from 'fs-extra';
import { normalizePath } from '../../utils/paths';
@@ -109,6 +109,8 @@ export async function createViteBuilder(
const plugins: NonNullable = [
wxtPlugins.entrypointGroupGlobals(entrypoint),
];
+ const iifeReturnValueName = safeVarName(entrypoint.name);
+
if (
entrypoint.type === 'content-script-style' ||
entrypoint.type === 'unlisted-style'
@@ -116,17 +118,16 @@ export async function createViteBuilder(
plugins.push(wxtPlugins.cssEntrypoints(entrypoint, wxtConfig));
}
- const iifeReturnValueName = safeVarName(entrypoint.name);
- const libMode: vite.UserConfig = {
+ if (
+ entrypoint.type === 'content-script' ||
+ entrypoint.type === 'unlisted-script'
+ ) {
+ plugins.push(wxtPlugins.iifeFooter(iifeReturnValueName));
+ }
+
+ return {
mode: wxtConfig.mode,
plugins,
- esbuild: {
- // Add a footer with the returned value so it can return values to `scripting.executeScript`
- // Footer is added a part of esbuild to make sure it's not minified. It
- // get's removed if added to `build.rollupOptions.output.footer`
- // See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value
- footer: iifeReturnValueName + ';',
- },
build: {
lib: {
entry,
@@ -162,8 +163,7 @@ export async function createViteBuilder(
// See https://github.com/aklinker1/vite-plugin-web-extension/issues/96
'process.env.NODE_ENV': JSON.stringify(wxtConfig.mode),
},
- };
- return libMode;
+ } satisfies vite.UserConfig;
};
/**
diff --git a/packages/wxt/src/core/builders/vite/plugins/iifeFooter.ts b/packages/wxt/src/core/builders/vite/plugins/iifeFooter.ts
new file mode 100644
index 00000000..604508ad
--- /dev/null
+++ b/packages/wxt/src/core/builders/vite/plugins/iifeFooter.ts
@@ -0,0 +1,20 @@
+import type { Plugin } from 'vite';
+
+/**
+ * Add a footer with the returned value so it can return values to `scripting.executeScript`
+ * Footer is added a part of esbuild to make sure it's not minified. It
+ * get's removed if added to `build.rollupOptions.output.footer`
+ * See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value
+ */
+export function iifeFooter(iifeReturnValueName: string): Plugin {
+ return {
+ name: 'wxt:iife-footer',
+ generateBundle(_, bundle) {
+ for (const chunk of Object.values(bundle)) {
+ if (chunk.type === 'chunk' && chunk.isEntry) {
+ chunk.code += `${iifeReturnValueName};`;
+ }
+ }
+ },
+ };
+}
diff --git a/packages/wxt/src/core/builders/vite/plugins/index.ts b/packages/wxt/src/core/builders/vite/plugins/index.ts
index 8f3b2714..27ea24c8 100644
--- a/packages/wxt/src/core/builders/vite/plugins/index.ts
+++ b/packages/wxt/src/core/builders/vite/plugins/index.ts
@@ -13,3 +13,4 @@ export * from './defineImportMeta';
export * from './removeEntrypointMainFunction';
export * from './wxtPluginLoader';
export * from './resolveAppConfig';
+export * from './iifeFooter';
diff --git a/packages/wxt/src/core/utils/building/build-entrypoints.ts b/packages/wxt/src/core/utils/building/build-entrypoints.ts
index 195a9d99..4edd2aff 100644
--- a/packages/wxt/src/core/utils/building/build-entrypoints.ts
+++ b/packages/wxt/src/core/utils/building/build-entrypoints.ts
@@ -4,7 +4,7 @@ import {
EntrypointGroup,
ResolvedPublicFile,
} from '../../../types';
-import { getPublicFiles } from '../../utils/fs';
+import { getPublicFiles } from '../fs';
import fs from 'fs-extra';
import { dirname, resolve } from 'path';
import type { Ora } from 'ora';
diff --git a/packages/wxt/src/utils/app-config.ts b/packages/wxt/src/utils/app-config.ts
index 7a22143f..e905d402 100644
--- a/packages/wxt/src/utils/app-config.ts
+++ b/packages/wxt/src/utils/app-config.ts
@@ -1,7 +1,7 @@
/** @module wxt/utils/app-config */
// @ts-expect-error: Untyped virtual module
import appConfig from 'virtual:app-config';
-import type { WxtAppConfig } from '../utils/define-app-config';
+import type { WxtAppConfig } from './define-app-config';
export function useAppConfig(): WxtAppConfig {
return appConfig;