thx / resvg-js

A high-performance SVG renderer and toolkit, powered by Rust based resvg and napi-rs.
https://resvg-js.vercel.app/
Mozilla Public License 2.0
1.56k stars 55 forks source link

TypeError: Invalid URL string. Used `initWasm()`. #288

Open tsuki-lab opened 9 months ago

tsuki-lab commented 9 months ago

Hello, An error occurred while developing a dynamic image generation function using @resvg/wasm and satori on Remix.

[initResvg] TypeError: Invalid URL string.
    at checkURL2 (y6vx947fiz.js:51:50)
    at Object.apply (y6vx947fiz.js:68:5)
    at __wbg_init (y6vx947fiz.js:46269:154)
    at initWasm (y6vx947fiz.js:46278:9)
    at async initResvg (y6vx947fiz.js:46339:5)
    at async Promise.all (index 1)
    at async loader (y6vx947fiz.js:46345:3)
    at async callRouteLoaderRR (y6vx947fiz.js:3589:16)
    at async callLoaderOrAction (y6vx947fiz.js:2669:16)
    at async Promise.all (index 0) {
  stack: TypeError: Invalid URL string.
    at checkURL2 (y…iz.js:2669:16)
    at async Promise.all (index 0),

https://github.com/tsuki-lab/remix-satori-resvg-cloudflare/blob/main/app/routes/og.tsx#L24 .

Error reproduction environment

dependency version
Remix 2.4.1
satori 0.10.11
yoga-wasm-web 0.3.3
@resvg/resvg-wasm 2.6.0

Deploy to cloudflare pages. And reproduce it locally.

Repository

https://github.com/tsuki-lab/remix-satori-resvg-cloudflare

yisibl commented 9 months ago

Try: import wasm from '@resvg/resvg-wasm/index_bg.wasm'

See: https://jross.me/improving-wasm-imports-with-wrangler-and-cloudflare-workers/

tsuki-lab commented 9 months ago

Try: import wasm from '@resvg/resvg-wasm/index_bg.wasm'

See: https://jross.me/improving-wasm-imports-with-wrangler-and-cloudflare-workers/

@yisibl I tried it, but the result did not change.

tsuki-lab commented 9 months ago

The version of wrangler I was using was an older version (3.8.0). I updated the version to the latest version (3.22.4) and when I checked, the error content had changed.

[initResvg] TypeError: Fetch API cannot load: /build/_assets/index_bg-FX7W6XMT.wasm

      at __wbg_init (file:///UsersDir/repo/node_modules/.pnpm/@resvg+resvg-wasm@2.6.0/node_modules/@resvg/resvg-wasm/index.mjs:528:13)
      at initWasm (file:///UsersDir/repo/node_modules/.pnpm/@resvg+resvg-wasm@2.6.0/node_modules/@resvg/resvg-wasm/index.mjs:542:9)
      at async initResvg (file:///UsersDir/repo/app/routes/og.tsx:23:5)
      at [object Object]
      at async loader (file:///UsersDir/repoapp/routes/og.tsx:31:3)
      at async callRouteLoaderRR (file:///UsersDir/repo/node_modules/.pnpm/@remix-run+server-runtime@2.4.1_typescript@5.3.3/node_modules/@remix-run/server-runtime/dist/esm/data.js:48:16)
      at async callLoaderOrAction (file:///UsersDir/repo/node_modules/.pnpm/@remix-run+router@1.14.1/node_modules/@remix-run/router/router.ts:4011:16)
      at [object Object]
      at async loadRouteData (file:///UsersDir/repo/node_modules/.pnpm/@remix-run+router@1.14.1/node_modules/@remix-run/router/router.ts:3298:19)
      at async queryImpl (file:///UsersDir/repo/node_modules/.pnpm/@remix-run+router@1.14.1/node_modules/@remix-run/router/router.ts:3076:20)
davidtranjs commented 8 months ago

I'm using this:

const wasmResponse = await fetch("https://unpkg.com/@resvg/resvg-wasm@2.6.0/index_bg.wasm");
const wasmArrayBuffer = await wasmResponse.arrayBuffer();
await initWasm(wasmArrayBuffer);
wouterds commented 7 months ago

Try: import wasm from '@resvg/resvg-wasm/index_bg.wasm'

See: https://jross.me/improving-wasm-imports-with-wrangler-and-cloudflare-workers/

Seems like the worker size gets too big and is unable to deploy then, I tried loading it from a remote URL but then I get stuck with [wrangler:err] CompileError: WebAssembly.instantiate(): Wasm code generation disallowed by embedder.

Code looks something like this


const initResvgWasm = async () => {
  try {
    await initResvg(
      // (await import('@resvg/resvg-wasm/index_bg.wasm')).default
      await fetch('https://unpkg.com/@resvg/resvg-wasm/index_bg.wasm').then((response) =>
        response.arrayBuffer(),
      ),
    );
  } catch (e) {
    if (e instanceof Error && !e.message.includes('Already initialized')) {
      throw e;
    }
  }
};

const initYogaWasm = async () => {
  const yoga = await initYoga(
    // (await import('yoga-wasm-web/dist/yoga.wasm')).default
    await fetch('https://unpkg.com/yoga-wasm-web/dist/yoga.wasm').then((response) =>
      response.arrayBuffer(),
    ),
  );
  initSatori(yoga);
};

And worker logs look something like this:

{
  "outcome": "exception",
  "scriptName": "pages-worker--2053183-preview",
  "diagnosticsChannelEvents": [],
  "exceptions": [
    {
      "name": "CompileError",
      "message": "WebAssembly.instantiate(): Wasm code generation disallowed by embedder",
      "timestamp": 1711227269214
    }
  ],
  "logs": [],
  "eventTimestamp": 1711227269168,
  "event": {
    "request": {
      [....]
    },
    "response": {
      "status": 500
    }
  },
  "id": 0
}
wilsonowilson commented 5 months ago

Using version 2.6.2 worked for me

import { initWasm } from '@resvg/resvg-wasm';

let initialized = false;

export async function initResvgWasm() {
    try {
        if (initialized) return;
        const wasmResponse = await fetch('https://unpkg.com/@resvg/resvg-wasm@2.6.2/index_bg.wasm');
        const wasmArrayBuffer = await wasmResponse.arrayBuffer();
        await initWasm(wasmArrayBuffer);
        initialized = true;
    } catch (error) {
        console.error('Resvg wasm not initialized', error);
    }
}