vite.config.ts

3.6 KB · raw

1import { defineConfig } from "vite";2import solidPlugin from "vite-plugin-solid";3import { crx } from "@crxjs/vite-plugin";4import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from "fs";5import { resolve } from "path";67const target = process.env.BUILD_TARGET || "chrome";8const manifestPath = target === "firefox" ? "./manifest.firefox.json" : "./manifest.json";9const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));10if (target === "chrome") {11  manifest.web_accessible_resources = [{12    matches: ["<all_urls>"],13    resources: ["<dynamic_resource>"],14    use_dynamic_url: true,15  }];16}17const passkeyE2E = process.env.PEACH_E2E_PASSKEYS === "1";18const outDir = target === "firefox" ? "dist-firefox" : "dist-chrome";1920// Copy the pdf.js worker into the build output so the popup can load it via21// chrome.runtime.getURL('pdf.worker.min.mjs'). The pdfjs-dist module's default22// workerSrc points inside node_modules, which is not reachable from a packaged23// extension — the worker file must sit alongside the rest of the assets.24const copyPdfJsWorker = {25  name: "copy-pdfjs-worker",26  closeBundle() {27    mkdirSync(outDir, { recursive: true });28    copyFileSync(29      resolve("node_modules/pdfjs-dist/build/pdf.worker.min.mjs"),30      resolve(outDir, "pdf.worker.min.mjs"),31    );32    if (target === "chrome") {33      const outputManifest = resolve(outDir, "manifest.json");34      const builtManifest = JSON.parse(readFileSync(outputManifest, "utf8"));35      for (const resource of builtManifest.web_accessible_resources ?? []) {36        resource.use_dynamic_url = true;37      }38      writeFileSync(outputManifest, `${JSON.stringify(builtManifest, null, 2)}\n`);39    }40  },41};4243export default defineConfig({44  plugins: [45    solidPlugin(),46    crx({ manifest, browser: target === "firefox" ? "firefox" : "chrome" }),47    copyPdfJsWorker,48  ],49  base: "./",50  define: {51    __PEACH_E2E_PASSKEYS__: JSON.stringify(passkeyE2E),52    __PEACH_DEBUG__: false,53  },54  build: {55    outDir,56    // emptyOutDir must stay false. When true, Vite tries to remove the57    // contents of the outDir before each build, which throws EPERM on FUSE58    // and some mounted filesystems and aborts the whole build. Overwriting59    // in place works everywhere.60    emptyOutDir: false,61    // The MV3 service worker has no `document`. Vite's module-preload helper62    // injects <link rel=modulepreload> via document.getElementsByTagName, and63    // it runs synchronously inside every dynamic import() that carries chunk64    // deps. In the worker that throws `ReferenceError: document is not defined`65    // synchronously — escaping the import's own .catch() and tearing down the66    // caller (e.g. passkey-get persisting signCount via fireSyncTrigger).67    // Disabling preload makes the helper a no-op; the link hints are only a68    // page-load micro-optimisation and the popup loads fine without them.69    modulePreload: false,70    target: "esnext",71    rollupOptions: {72      // HV-2: the offscreen document (Chrome only — Firefox has no73      // chrome.offscreen) must be bundled and emitted so the background can74      // load it via chrome.offscreen.createDocument. Firefox capability-checks75      // chrome.offscreen and never references it.76      input:77        target === "firefox"78          ? undefined79          : { offscreen: resolve("src/background/offscreen.html") },80      output: {81        manualChunks(id) {82          if (id.includes("node_modules/solid-js")) return "vendor-solid";83          if (id.includes("node_modules/otpauth")) return "vendor-otp";84          if (id.includes("node_modules/papaparse")) return "vendor-parse";85        },86      },87    },88  },89});