diff --git a/with-skia/components/async-skia.tsx b/with-skia/components/async-skia.tsx index 13936658..f7bdd55d 100644 --- a/with-skia/components/async-skia.tsx +++ b/with-skia/components/async-skia.tsx @@ -1,51 +1,15 @@ // Helper to ensure Skia loads or throws inside of React Suspense on web. -import React from "react"; - +import { use } from "react"; import { LoadSkiaWeb } from "@shopify/react-native-skia/lib/module/web"; -function wrapPromise(promise: Promise) { - let status: "pending" | "success" | "error" = "pending"; - let result: T | unknown; - let suspender = promise.then( - (r: T) => { - status = "success"; - result = r; - }, - (e: unknown) => { - status = "error"; - result = e; - } - ); - return { - read(): T { - if (status === "pending") { - throw suspender; - } else if (status === "error") { - throw result; - } else if (status === "success") { - return result as T; - } - throw new Error("Unexpected state"); - }, - }; -} - -const promiseMap = new Map(); +let skiaPromise: Promise | null = null; -const getSuspendingPromise = () => { - const id = "skia"; - if (!promiseMap.has(id)) { - const loader = wrapPromise(LoadSkiaWeb()); - promiseMap.set(id, loader); - return loader.read(); - } - - return promiseMap.get(id).read(); -}; - -const getResolvedPromise = React.cache(getSuspendingPromise); +function loadSkia() { + if (!skiaPromise) skiaPromise = LoadSkiaWeb(); + return skiaPromise; +} -export function AsyncSkia({}) { - getResolvedPromise(); +export function AsyncSkia() { + use(loadSkia()); return null; } diff --git a/with-skia/copy-canvaskit.js b/with-skia/copy-canvaskit.js new file mode 100644 index 00000000..42c32458 --- /dev/null +++ b/with-skia/copy-canvaskit.js @@ -0,0 +1,14 @@ +// This script is used to copy canvaskit.wasm from node_modules to public folder + +const fs = require("fs"); +const path = require("path"); + +const publicFolder = path.join(process.cwd(), "public"); +fs.mkdirSync(publicFolder, { recursive: true }); + +const wasmSrc = require.resolve("canvaskit-wasm/bin/full/canvaskit.wasm", { + paths: [require.resolve("@shopify/react-native-skia")], +}); + +const wasmDest = path.join(publicFolder, "canvaskit.wasm"); +fs.copyFileSync(wasmSrc, wasmDest); diff --git a/with-skia/package.json b/with-skia/package.json index b6bf44f8..da1d5adb 100644 --- a/with-skia/package.json +++ b/with-skia/package.json @@ -3,18 +3,18 @@ "main": "expo-router/entry", "scripts": { "start": "expo start", - "postinstall": "mkdir public; cp $(node -p \"require.resolve('canvaskit-wasm/bin/full/canvaskit.wasm', { paths: [require.resolve('@shopify/react-native-skia')] })\") public/canvaskit.wasm", + "postinstall": "node copy-canvaskit.js", "deploy": "npx expo export -p web && npx eas-cli@latest deploy" }, "dependencies": { "@shopify/react-native-skia": "2.2.12", "expo": "^54.0.1", "expo-linking": "^8.0.8", - "expo-router": "~6.0.0", + "expo-router": "~6.0.22", "react": "19.1.0", "react-dom": "19.1.0", - "react-native": "0.81.4", - "react-native-reanimated": "^4.1.3", + "react-native": "0.81.5", + "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "^5.6.1", "react-native-screens": "~4.16.0", "react-native-web": "^0.21.0",