Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions packages/wxt/e2e/tests/output-structure.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, it, expect } from 'vitest';
import { describe, expect, it } from 'vitest';
import { TestProject } from '../utils';

describe('Output Directory Structure', () => {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -397,7 +395,6 @@ describe('Output Directory Structure', () => {
const result$1 = result;
return result$1;
}();
background;
"
`);
});
Expand Down
24 changes: 12 additions & 12 deletions packages/wxt/src/core/builders/vite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -109,24 +109,25 @@ export async function createViteBuilder(
const plugins: NonNullable<vite.UserConfig['plugins']> = [
wxtPlugins.entrypointGroupGlobals(entrypoint),
];
const iifeReturnValueName = safeVarName(entrypoint.name);

if (
entrypoint.type === 'content-script-style' ||
entrypoint.type === 'unlisted-style'
) {
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,
Expand Down Expand Up @@ -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;
};

/**
Expand Down
20 changes: 20 additions & 0 deletions packages/wxt/src/core/builders/vite/plugins/iifeFooter.ts
Original file line number Diff line number Diff line change
@@ -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};`;
Copy link

@sm17p sm17p Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but linking relevant issues for support at bundler level

  1. top level return for IIFEs rollup/rollup#5509 (comment)
  2. this.parse now only supports the allowReturnOutsideFunction option for now ([v4.0] Switch parser to SWC and introduce native/WASM code rollup/rollup#5073)

  3. feat!: rollup v4 vitejs/vite#14508

Copy link
Contributor Author

@PatrykKuniczak PatrykKuniczak Jul 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sm17p I don't understand.
What are you want to achive, i need to adjust my code or what?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I found is that there is a rollup specific option called allowReturnOutsideFunction which does what this plugin is trying to do.

The first issue has usage examples for areas where we need that option for code transformation.

The 2nd and 3rd are just supporting issues indicating that it's available for use for Vite v6.

Why I mentioned it?

  • I thought if it's available at a bundler level, then it's better to use that to avoid maintenance overhead.

i need to adjust my code or what?

  • Upto the owner's descretion
  • Normally, what I would do is check if I can get it working with already existing API but that's your call

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sm17p Now i see, what are you want to achive.

But this prop could be use only inside plugin context, i need to make plugin after all, especially if we want to run it under condition(Only for content-script and unlisted-script)

I was studying the structure of project and of building process, and there's no place do enable it for plugin of one of entrypoints, because it's fetching dynamically, and there's no plugin for e.g content-script in which plugin i can enable allowReturnOutsideFunction.

Maybe there's a chance. owner will answer, i'm still begginer in this project :)

Now it's simply IMO, but if it could be more simply, let's feel free to open PR to my branch with your solution or wait for owner answer, we knows more than us, about his product :)

}
}
},
};
}
1 change: 1 addition & 0 deletions packages/wxt/src/core/builders/vite/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from './defineImportMeta';
export * from './removeEntrypointMainFunction';
export * from './wxtPluginLoader';
export * from './resolveAppConfig';
export * from './iifeFooter';
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt/src/utils/app-config.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Loading