Fix native build: access Camera via runtime plugin, not @capacitor/camera import
Local CAPACITOR_BUILD failed: Rollup couldn't resolve import
"@capacitor/camera" from CameraCapture.tsx — the package is listed in
package.json but isn't present in node_modules on the build machine.
Root pattern (same class as the @capacitor/core crash): a package that
must NOT be resolved at build time was being imported by specifier.
Fix:
- CameraCapture.tsx no longer imports '@capacitor/camera' at all. The
Camera plugin is accessed via the runtime-injected
window.Capacitor.Plugins.Camera (Capacitor injects it natively), using
string enum values ('dataUrl' / 'CAMERA'). No bare specifier remains in
the bundle, and it degrades gracefully if the plugin is absent.
- vite.config: @capacitor/camera moved back to `external` (belt-and-braces;
it's no longer imported anyway). @capacitor/core stays BUNDLED (static
import in platform.ts — the white-screen fix). nostr-signer-capacitor-plugin
and the 4 uninstalled @capacitor/* plugins remain external.
Verified: no @capacitor/camera specifier and no unresolved @capacitor/core
import in the built bundle; no static imports of any externalized package
remain in src/. Bump to 1.0.67.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
ac362a9a10
commit
3a96184001
3 changed files with 45 additions and 18 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "skate-spots",
|
||||
"private": true,
|
||||
"version": "1.0.66",
|
||||
"version": "1.0.67",
|
||||
"type": "module",
|
||||
"homepage": "https://skate-spots.com",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -42,11 +42,34 @@ async function isNative(): Promise<boolean> {
|
|||
}
|
||||
}
|
||||
|
||||
// The Camera plugin is provided by Capacitor at runtime on native. We access it
|
||||
// through the runtime-injected `window.Capacitor.Plugins.Camera` rather than a
|
||||
// static/dynamic `import('@capacitor/camera')`, so the bundle contains no bare
|
||||
// `@capacitor/camera` specifier (which a native WebView can't resolve, and which
|
||||
// isn't installed on every build machine). CameraResultType/CameraSource are
|
||||
// plain string enums in the plugin, so we pass their string values directly.
|
||||
interface CapacitorCameraPlugin {
|
||||
getPhoto(options: {
|
||||
resultType: string;
|
||||
source: string;
|
||||
quality: number;
|
||||
correctOrientation: boolean;
|
||||
}): Promise<{ dataUrl?: string }>;
|
||||
}
|
||||
|
||||
function getNativeCamera(): CapacitorCameraPlugin | null {
|
||||
const cap = (window as unknown as {
|
||||
Capacitor?: { Plugins?: { Camera?: CapacitorCameraPlugin } };
|
||||
}).Capacitor;
|
||||
return cap?.Plugins?.Camera ?? null;
|
||||
}
|
||||
|
||||
async function captureNative(): Promise<File | null> {
|
||||
const { Camera, CameraResultType, CameraSource } = await import('@capacitor/camera');
|
||||
const Camera = getNativeCamera();
|
||||
if (!Camera) throw new Error('Camera plugin unavailable');
|
||||
const photo = await Camera.getPhoto({
|
||||
resultType: CameraResultType.DataUrl,
|
||||
source: CameraSource.Camera,
|
||||
resultType: 'dataUrl', // CameraResultType.DataUrl
|
||||
source: 'CAMERA', // CameraSource.Camera
|
||||
quality: 90,
|
||||
correctOrientation: true,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -44,22 +44,26 @@ export default defineConfig(() => ({
|
|||
transformMixedEsModules: true,
|
||||
},
|
||||
rollupOptions: {
|
||||
// IMPORTANT: @capacitor/core and @capacitor/camera MUST be bundled (they are
|
||||
// installed, statically imported, and their JS API layer is real code the
|
||||
// WebView needs). Leaving them external emitted a bare `import "@capacitor/core"`
|
||||
// specifier that a native WebView cannot resolve → white-screen boot crash.
|
||||
// They are therefore intentionally ABSENT from this list.
|
||||
// Bundling policy — the distinction that matters is STATIC vs DYNAMIC import,
|
||||
// and whether the package resolves on the build machine:
|
||||
//
|
||||
// Kept external:
|
||||
// - nostr-signer-capacitor-plugin: installed from GitHub with a broken package
|
||||
// entry point, so it CANNOT be bundled. It's only ever used via a guarded
|
||||
// dynamic import() at runtime on native (see lib/capacitorAmberSigner.ts,
|
||||
// wrapped in try/catch → returns null on failure), so external is correct
|
||||
// and safe — a resolution failure degrades gracefully instead of crashing.
|
||||
// - @capacitor/app|haptics|keyboard|status-bar: NOT installed and never
|
||||
// statically imported (accessed via window.Capacitor.Plugins), so keeping
|
||||
// them external prevents a stray import from breaking the build.
|
||||
// BUNDLED (absent from this list):
|
||||
// - @capacitor/core — imported STATICALLY (lib/platform.ts). It MUST be
|
||||
// bundled: leaving it external emitted a bare `import "@capacitor/core"`
|
||||
// specifier the native WebView can't resolve → white-screen boot crash.
|
||||
// Capacitor guarantees core is installed, so bundling always resolves.
|
||||
//
|
||||
// EXTERNAL (listed below):
|
||||
// - @capacitor/camera — used only via a GUARDED dynamic import() on native
|
||||
// (components/CameraCapture.tsx). It may not be installed on every build
|
||||
// machine, and it's optional/native-only, so it must stay external. The
|
||||
// dynamic import() remains a runtime call that degrades gracefully.
|
||||
// - nostr-signer-capacitor-plugin — installed from GitHub with a broken
|
||||
// package entry point; cannot be bundled. Guarded dynamic import() only.
|
||||
// - @capacitor/app|haptics|keyboard|status-bar — NOT installed and never
|
||||
// statically imported (accessed via window.Capacitor.Plugins at runtime).
|
||||
external: [
|
||||
'@capacitor/camera',
|
||||
'nostr-signer-capacitor-plugin',
|
||||
'@capacitor/app',
|
||||
'@capacitor/haptics',
|
||||
|
|
|
|||
Loading…
Reference in a new issue