1

There's an issue with importing es modules into the content script: (How to import ES6 modules in content script for Chrome Extension)

Maybe there is a way to build the content script in one file to resolve this?

I'm using this boilerplate - https://github.com/JohnBra/vite-web-extension. Here's what my vite config looks like:

import react from "@vitejs/plugin-react-swc";
import { resolve } from "path";
import { defineConfig } from "vite";
import copyContentStyle from "./utils/plugins/copy-content-style";
import makeManifest from "./utils/plugins/make-manifest";

const root = resolve(__dirname, "src");
const pagesDir = resolve(root, "pages");
const assetsDir = resolve(root, "assets");
const outDir = resolve(__dirname, "dist");
const publicDir = resolve(__dirname, "public");

const IS_DEV = process.env.DEV === "true";

export default defineConfig({
  resolve: {
    alias: {
      "@src": root,
      "@assets": assetsDir,
      "@pages": pagesDir,
    },
  },
  plugins: [react(), makeManifest(), copyContentStyle()],
  publicDir,
  build: {
    minify: !IS_DEV,
    outDir,
    sourcemap: IS_DEV,
    emptyOutDir: IS_DEV,
    rollupOptions: {
      input: {
        // devtools: resolve(pagesDir, 'devtools', 'index.html'),
        // panel: resolve(pagesDir, "panel", "index.html"),
        content: resolve(pagesDir, "content", "index.ts"),
        background: resolve(pagesDir, "background", "index.ts"),
        popup: resolve(pagesDir, "popup", "index.html"),
        // newtab: resolve(pagesDir, "newtab", "index.html"),
        // options: resolve(pagesDir, "options", "index.html"),
      },
      output: {
        entryFileNames: (chunk) => {
          return `src/pages/${chunk.name}/index.js`;
        },
      },
    },
  },
});

I tried having a separate vite config for the content scripts to build it in one file. But, I was not successful

Here's what the config for that looks like:

import { resolve } from "path";
import { defineConfig } from "vite";
import copyContentStyle from "./utils/plugins/copy-content-style";
import { viteSingleFile } from "vite-plugin-singlefile";

const root = resolve(__dirname, "src");
const pagesDir = resolve(root, "pages");
const assetsDir = resolve(root, "assets");
const outDir = resolve(__dirname, "dist");
const publicDir = resolve(__dirname, "public");

const IS_DEV = process.env.DEV === "true";

export default defineConfig({
  resolve: {
    alias: {
      "@src": root,
      "@assets": assetsDir,
      "@pages": pagesDir,
    },
  },
  plugins: [copyContentStyle(), viteSingleFile()],
  publicDir,
  build: {
    minify: !IS_DEV,
    outDir,
    sourcemap: IS_DEV,
    emptyOutDir: IS_DEV,
    rollupOptions: {
      input: {
        content: resolve(pagesDir, "content", "index.ts"),
      },
      output: {
        dir: `src/pages/content`,
      },
    },
  },
});
mr0b0t0
  • 53
  • 8

2 Answers2

1

I ended up having a separate vite config for the content script, which looks like:

import { resolve } from "path";
import { defineConfig } from "vite";
import { viteSingleFile } from "vite-plugin-singlefile";

const root = resolve(__dirname, "src");
const pagesDir = resolve(root, "pages");
const outDir = resolve(__dirname, "dist", "src", "pages", "content");

const IS_DEV = process.env.DEV === "true";

export default defineConfig({
  resolve: {
    alias: {
      "@src": root,
      "@pages": pagesDir,
    },
  },
  plugins: [viteSingleFile()],
  build: {
    copyPublicDir: false,
    minify: !IS_DEV,
    outDir,
    sourcemap: IS_DEV,
    emptyOutDir: IS_DEV,
    rollupOptions: {
      input: {
        content: resolve(pagesDir, "content", "index.ts"),
      },
      output: {
        entryFileNames: "index.js",
      },
    },
  },
});

And, I run it all with:

  "scripts": {
    "build:general": "vite build",
    "build:content": "vite build --config vite.contentScript-config.ts",
    "build": "run-p build:*",
    "dev:general": "vite build --watch --mode development",
    "dev:content": "vite build --config vite.contentScript-config.ts --watch --mode development",
    "dev": "run-p dev:*"
  },
mr0b0t0
  • 53
  • 8
0

If you're already building with react and Vite, check out CRXjs. Handy utility for building extensions.

The plugin will take care of how content and service worker files are made available to the extension (see docs as well). Huge plus is HMR while you're developing.

Should make it easy to write you manifest in ts/js (esm) and pass that to the vite config like so:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.json' // or manifest.ts / manifest.js

export default defineConfig({
  plugins: [
    react(),
    crx({ 
      manifest // <--- pass in your manifest here
    }),
  ],
})

assuming a valid (MV3) manifest like:


const manifest = {
 name: 'extension-name'
 version: '0.0.1',
 manifest_version: 3,
 // ...other manifest fields
}
JoeyDoey
  • 11
  • 3