SkateSpots/vite.config.ts
shakespeare.diy 0a47bb47d2 Fix native crash: bundle @capacitor/core instead of externalizing it
The boot crash guard surfaced the real root cause on-device:
  TypeError: Failed to resolve module specifier "@capacitor/core"

@capacitor/core and @capacitor/camera were marked `external` in the
Rollup config, which left bare `import "@capacitor/core"` specifiers in
the output bundle. A native WebView has no module resolver for bare
specifiers, so boot crashed before React mounted.

Fix: remove the INSTALLED Capacitor packages from `external` so their JS
API layer is bundled (the native implementation is still injected at
runtime via window.Capacitor). Only the four NON-installed packages
(@capacitor/app, haptics, keyboard, status-bar) stay external — they are
never statically imported (accessed via window.Capacitor.Plugins), so
this can't break the build.

Bump to 1.0.65.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-24 18:31:26 +07:00

113 lines
3.9 KiB
TypeScript

import path from "node:path";
import react from "@vitejs/plugin-react-swc";
import { defineConfig } from "vitest/config";
// https://vitejs.dev/config/
export default defineConfig(() => ({
// In a native Capacitor WebView the bundle is served from the local
// filesystem, so assets must be referenced with RELATIVE paths ('./…').
// Absolute '/…' paths are the classic cause of a white screen on device.
// The regular web deploy keeps '/' (served from a domain root).
base: process.env.CAPACITOR_BUILD ? './' : '/',
server: {
host: "::",
port: 8080,
},
plugins: [
react(),
],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
onConsoleLog(log) {
return !log.includes("React Router Future Flag Warning");
},
env: {
DEBUG_PRINT_LIMIT: '0',
},
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
optimizeDeps: {
exclude: ['@lightninglabs/lnc-web'],
},
build: {
// Strip console.log/warn/debug in production (keeps console.error for real errors)
minify: 'esbuild',
commonjsOptions: {
transformMixedEsModules: true,
},
rollupOptions: {
// IMPORTANT: installed Capacitor packages (@capacitor/core, @capacitor/camera)
// and the signer plugin MUST be bundled. Their JS API layer is real code that
// the WebView needs — the *native* implementation is injected at runtime via
// window.Capacitor, but the JS imports have to resolve. Externalizing them
// leaves bare `import "@capacitor/core"` specifiers in the output, which a
// native WebView cannot resolve → "Failed to resolve module specifier" crash.
//
// Only the Capacitor packages that are NOT installed are kept external, so a
// stray import can't break the build. If one of these is ever added to
// package.json, remove it from this list so it gets bundled.
external: [
'@capacitor/app',
'@capacitor/haptics',
'@capacitor/keyboard',
'@capacitor/status-bar',
],
output: process.env.CAPACITOR_BUILD ? {
// Single bundle for Capacitor APK — avoids 100+ chunk file requests
// that fail silently in Android WebView local file serving
manualChunks: undefined,
inlineDynamicImports: true,
} : {
// Split large vendor libraries into separate cacheable chunks.
// Users only re-download a chunk when that specific library updates.
manualChunks(id) {
// Map — Leaflet is large (~150KB), isolate it so non-map pages don't pay for it
if (id.includes('leaflet') || id.includes('ngeohash')) {
return 'vendor-map';
}
// Nostr core — changes infrequently, worth caching separately
if (id.includes('nostr-tools') || id.includes('@nostrify') || id.includes('@noble')) {
return 'vendor-nostr';
}
// Bitcoin / Lightning — large, rarely changes
if (
id.includes('@cashu') ||
id.includes('bitcoinjs-lib') ||
id.includes('@scure') ||
id.includes('@bitcoinerlab') ||
id.includes('ecpair') ||
id.includes('@getalby') ||
id.includes('npubcash')
) {
return 'vendor-bitcoin';
}
// React ecosystem — very stable, long cache life
if (id.includes('react-dom') || id.includes('react-router')) {
return 'vendor-react';
}
// Radix UI components — large but stable
if (id.includes('@radix-ui')) {
return 'vendor-radix';
}
// TanStack Query
if (id.includes('@tanstack')) {
return 'vendor-query';
}
},
},
},
},
// Strip console.log/warn/debug calls from production build
esbuild: {
drop: ['debugger'],
pure: ['console.log', 'console.warn', 'console.debug'],
},
}));