fix: content scripts not loading because of dynamic ES modules

This commit is contained in:
Abhijith Vijayan [FLUXON] 2026-01-03 21:06:31 +05:30
parent 74d10f2424
commit 710ad4f714

View File

@ -1,4 +1,4 @@
import { defineConfig } from 'vite'; import {defineConfig, build} from 'vite';
import path from 'node:path'; import path from 'node:path';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
import process from 'node:process'; import process from 'node:process';
@ -7,6 +7,46 @@ import checker from 'vite-plugin-checker';
import clean from 'vite-plugin-clean'; import clean from 'vite-plugin-clean';
import WextManifest from 'vite-plugin-wext-manifest'; import WextManifest from 'vite-plugin-wext-manifest';
import type {Plugin} from 'vite';
// Custom plugin to build content scripts as IIFE (self-contained, no ES module imports)
function buildContentScripts(options: {
scripts: {name: string; entry: string}[];
outDir: string;
isDevelopment: boolean;
}): Plugin {
return {
name: 'build-content-scripts',
async writeBundle() {
for (const script of options.scripts) {
await build({
configFile: false,
build: {
write: true,
outDir: options.outDir,
emptyOutDir: false,
sourcemap: options.isDevelopment ? 'inline' : false,
minify: !options.isDevelopment,
rollupOptions: {
input: script.entry,
output: {
entryFileNames: `assets/js/${script.name}.bundle.js`,
format: 'iife',
inlineDynamicImports: true,
},
},
lib: {
entry: script.entry,
formats: ['iife'],
name: script.name,
},
},
});
}
},
};
}
export default defineConfig(({ mode }) => { export default defineConfig(({ mode }) => {
const isDevelopment = mode !== 'production'; const isDevelopment = mode !== 'production';
const sourcePath = path.resolve(__dirname, 'source'); const sourcePath = path.resolve(__dirname, 'source');
@ -69,6 +109,19 @@ export default defineConfig(({ mode }) => {
usePackageJSONVersion: true, usePackageJSONVersion: true,
}), }),
// Build content scripts as IIFE (no ES module imports)
// Content scripts can't use ES modules in manifest-injected scripts
buildContentScripts({
scripts: [
{
name: 'contentScript',
entry: path.resolve(sourcePath, 'ContentScript/index.ts'),
},
],
outDir: getOutDir(),
isDevelopment,
}),
!isDevelopment && !isDevelopment &&
zipPack({ zipPack({
inDir: getOutDir(), inDir: getOutDir(),
@ -93,29 +146,19 @@ export default defineConfig(({ mode }) => {
// Vite will find the <script> tag inside and bundle it. // Vite will find the <script> tag inside and bundle it.
popup: path.resolve(sourcePath, 'Popup/popup.html'), popup: path.resolve(sourcePath, 'Popup/popup.html'),
options: path.resolve(sourcePath, 'Options/options.html'), options: path.resolve(sourcePath, 'Options/options.html'),
// For script-only parts, use the TS file directly. // Background script (service worker in MV3)
background: path.resolve(sourcePath, 'Background/index.ts'), background: path.resolve(sourcePath, 'Background/index.ts'),
contentScript: path.resolve(sourcePath, 'ContentScript/index.ts'), // Note: contentScript is built separately as IIFE via buildContentScripts plugin
}, },
output: { output: {
// For main entry scripts (background, contentScript, etc.)
entryFileNames: 'assets/js/[name].bundle.js', entryFileNames: 'assets/js/[name].bundle.js',
// For other assets like CSS
assetFileNames: (assetInfo) => { assetFileNames: (assetInfo) => {
if ( if (assetInfo.names?.[0]?.match(/\.(css|s[ac]ss|less)$/)) {
!!assetInfo.name &&
/\.(css|s[ac]ss|less)$/.test(assetInfo.name)
) {
return 'assets/css/[name]-[hash].css'; return 'assets/css/[name]-[hash].css';
} }
// For other assets like fonts or images
return 'assets/[name]-[hash].[ext]'; return 'assets/[name]-[hash].[ext]';
}, },
// For code-split chunks (if any)
chunkFileNames: 'assets/js/[name]-[hash].chunk.js', chunkFileNames: 'assets/js/[name]-[hash].chunk.js',
}, },
}, },