mcpField
C
chrome-extension-multiple-entry-points

chrome-extension-multiple-entry-points

github.com/gkwaDevelopment088 installsUpdated 5d ago
Repository

About chrome-extension-multiple-entry-points

A build pattern for Chrome extensions with background, content, and popup entry points. It uses a separate Vite config for each entry to emit self-contained IIFE bundles without shared chunks.

Key features

  1. 01Separate Vite config per entry point
  2. 02Self-contained IIFE output
  3. 03Inline dynamic imports
  4. 04Append builds to dist/
  5. 05Cross-platform asset copy commands

Use cases

  1. 01Bundling background, content, and popup scripts
  2. 02Avoiding shared chunks across extension contexts
  3. 03Building extension assets into dist/

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/gkwa/volcanicviper --skill chrome-extension-multiple-entry-points

After installing, type/chrome-extension-multiple-entry-pointsin Claude Code to confirm it loaded.

Bundled filestile.json

Details

From the project README

The Problem

Chrome extensions need multiple entry points (background, content, popup), but modern bundlers create shared chunks that Chrome cannot load across isolated execution contexts.

The Solution

Use a separate Vite config file for each entry point. Each build produces a self-contained IIFE file with no shared chunks.

Project Structure

my-extension/
├── src/
│   ├── background/background.ts
│   ├── content/content.ts
│   ├── popup/
│   │   ├── popup.ts
│   │   ├── popup.html
│   │   └── popup.css
│   └── manifest.json
├── vite.background.config.ts
├── vite.content.config.ts
├── vite.popup.config.ts
└── package.json

package.json Scripts

{
  "scripts": {
    "build": "shx rm -rf dist && shx mkdir -p dist && pnpm run build:all && pnpm run copy:assets",
    "build:all": "pnpm run build:background && pnpm run build:content && pnpm run build:popup",
    "build:background": "vite build --config vite.background.config.ts",
    "build:content": "vite build --config vite.content.config.ts",
    "build:popup": "vite build --config vite.popup.config.ts",
    "copy:assets": "shx cp src/manifest.json src/popup/popup.html src/popup/popup.css dist/",
    "dev": "pnpm run build && pnpm run build --watch"
  },
  "devDependencies": {
    "@types/chrome": "^0.0.323",
    "typescript": "^5.8.3",
    "vite": "^6.3.5",
    "shx": "^0.3.4"
  }
}

Vite Config Pattern

Each config follows the same pattern — only the input file and output filename differ:

import { defineConfig } from "vite"
import { resolve } from "path"

export default defineConfig({
  build: {
    emptyOutDir: false,
    rollupOptions: {
      input: resolve(__dirname, "src/background/background.ts"),
      output: {
        entryFileNames: "background.js",
        dir: "dist",
        format: "iife",
        inlineDynamicImports: true,
      },
    },
    target: "es2020",
  },
  define: {
    'process.env': {},
    'global': 'globalThis'
  },
})

Key Rules

  • Use format: "iife" — not ES modules
  • Set inlineDynamicImports: true — no shared chunks
  • Use emptyOutDir: false — each build appends to dist/, not overwrites
  • Use shx for cross-platform copy/rm commands
  • Accept that dependencies are duplicated across bundles — that is intentional

Comments

Markdown supported