vite.config.ts raw

   1  import tailwindcss from "@tailwindcss/vite";
   2  import react from "@vitejs/plugin-react-swc";
   3  import path from "path";
   4  import { defineConfig, Plugin } from "vite";
   5  import { VitePWA } from "vite-plugin-pwa";
   6  
   7  export default defineConfig(({ command }) => ({
   8    plugins: [
   9      react(),
  10      tailwindcss(),
  11      VitePWA({
  12        registerType: "autoUpdate",
  13        // disable service worker - Alby Hub cannot be used offline (and also breaks oauth callback)
  14        injectRegister: false,
  15        includeAssets: [
  16          "favicon.ico",
  17          "robots.txt",
  18          "icon-192.png",
  19          "icon-512.png",
  20        ],
  21        useCredentials: true, // because the manifest might sit behind authentication
  22        manifest: {
  23          short_name: "Alby Hub",
  24          name: "Alby Hub",
  25          icons: [
  26            {
  27              src: "icon-192.png",
  28              sizes: "192x192",
  29              type: "image/png",
  30            },
  31            {
  32              src: "icon-512.png",
  33              sizes: "512x512",
  34              type: "image/png",
  35            },
  36            {
  37              src: "icon-1024.png",
  38              sizes: "1024x1024",
  39              type: "image/png",
  40            },
  41          ],
  42          start_url: ".",
  43          display: "standalone",
  44          theme_color: "#000000",
  45          background_color: "#ffffff",
  46        },
  47        workbox: {
  48          maximumFileSizeToCacheInBytes: 3000000, // 3MB
  49        },
  50      }),
  51      ...(command === "serve" ? [insertDevCSPPlugin] : [insertProdCSPPlugin]),
  52    ],
  53    server: {
  54      port: process.env.VITE_PORT ? parseInt(process.env.VITE_PORT) : undefined,
  55      proxy: {
  56        "/api": {
  57          target: process.env.VITE_API_URL || "http://localhost:8080",
  58          secure: false,
  59        },
  60        "/logout": {
  61          target: process.env.VITE_API_URL || "http://localhost:8080",
  62          secure: false,
  63        },
  64      },
  65    },
  66    resolve: {
  67      tsconfigPaths: true,
  68      alias: {
  69        src: path.resolve(import.meta.dirname, "./src"),
  70        wailsjs: path.resolve(import.meta.dirname, "./wailsjs"),
  71        // used to refrence public assets when importing images or other
  72        // assets from the public folder
  73        // this is necessary to inject the base path during build
  74        public: "",
  75        // lottie-react's `browser` field points to a UMD build, which breaks
  76        // under Vite 8's Node-style CJS interop (default import resolves to the
  77        // whole exports object); force the ESM build instead
  78        "lottie-react": "lottie-react/build/index.es.js",
  79      },
  80    },
  81    build: {
  82      assetsInlineLimit: 0,
  83    },
  84    html:
  85      command === "serve"
  86        ? {
  87            cspNonce: "DEVELOPMENT",
  88          }
  89        : undefined,
  90    base: process.env.BASE_PATH || "/",
  91  }));
  92  
  93  const DEVELOPMENT_NONCE = "'nonce-DEVELOPMENT'";
  94  
  95  // when making changes here, also update the CSP header in http_service.go
  96  const buildCSP = (nonce?: string) =>
  97    `default-src 'self'${nonce ? " " + nonce : ""}; img-src 'self' https://uploads.getalby-assets.com https://cdn.getalby-assets.com https://getalby.com; connect-src 'self' https://api.getalby.com https://getalby.com https://zapplanner.albylabs.com wss://relay.mleku.dev wss://relay.getalby.com wss://relay2.getalby.com; frame-src https://www.youtube-nocookie.com`;
  98  
  99  const insertCSPMetaTag = (comment: string, csp: string) => (html: string) =>
 100    html.replace(
 101      "<head>",
 102      `<head>
 103          <!-- ${comment} -->
 104          <meta http-equiv="Content-Security-Policy" content="${csp}" />`
 105    );
 106  
 107  const insertDevCSPPlugin: Plugin = {
 108    name: "dev-csp",
 109    transformIndexHtml: {
 110      order: "pre",
 111      handler: insertCSPMetaTag(
 112        "DEV-ONLY CSP - when making changes here, also update the CSP header in http_service.go (without the nonce!)",
 113        buildCSP(DEVELOPMENT_NONCE)
 114      ),
 115    },
 116  };
 117  
 118  // the same CSP is served as a HTTP header in http mode (see http_service.go).
 119  // The meta tag ensures the policy also applies where no HTTP headers are set,
 120  // e.g. in the desktop app.
 121  const insertProdCSPPlugin: Plugin = {
 122    name: "prod-csp",
 123    transformIndexHtml: {
 124      order: "pre",
 125      handler: insertCSPMetaTag(
 126        "when making changes here, also update the CSP header in http_service.go",
 127        buildCSP()
 128      ),
 129    },
 130  };
 131