Wasm problem with Sveltekit, Cloudflare Pages and ...
# general-help
b
I'm trying to implement dynamic opengraph images, and so far the most promising solution has been satori + Resvg on a server endpoint (turns into a cloudflare pages function). It works beautifully everywhere except deployed on Cloudflare.
"CompileError: WebAssembly.instantiate(): Wasm code generation disallowed by embedder"
I found this "workaround" which does not seem to work: https://github.com/cloudflare/workers-sdk/issues/1366 which defines a wasm
Memory
to a 512 pagesize to be able to work on Cloudflare. The wasm package I'm trying to use is Resvg. which I import via fetch using Vite's
..wasm?url
directive because Vite doesn't support ESM wasm modules especially in SSR. I tried using vite plugins for directly importing wasm modules (like
vite-plugin-wasm
and also mentioned here https://github.com/vitejs/vite/issues/8882) with no success because then it throws a
cannot find module 'wbg'
error. I understand there are tons of factors frameworks and tools associated with this but if anyone can help me at all tha'd be amazing
j
While not directly a solution for you, I can confirm that I'm able to use
resvg-wasm
without issue in Workers when I import it directly via
import wasm from '@resvg/resvg-wasm/index_bg.wasm'
and do so in a couple projects. I don't know how/if that'll work when it interacts with Vite though.
b
Thank you, when I try that, i get some error with
wbg
which i know nothing about and it seems specific to how resvg is packing their wasm
lemme try it and spit out the error
j
When using
wrangler dev
directly or via some build step with Vite? It works perfectly fine for me in a couple Workers projects, though I'm just doing them directly and using
wrangler
or
esbuild
instead of another build step
b
yeah I get this error when importing
'@resvg/resvg-wasm/index_bg.wasm'
Copy code
Error: Cannot find module 'wbg' imported from 'C:/Users/.../node_modules/@resvg/resvg-wasm/index_bg.wasm'
I'm not using wrangler dev. just normal build with Vite, using the sveltekit adapter for cloudflare
In dev. havent tried deploying that. but dont know why this error would disappear
j
Hmm yeah okay I suspect this is some way that svelte/vite is bundling that wasm file. It definitely works fine in Workers directly, but something in the build chain here is doing something weird
I'm not super familiar with Vite/Svelte internals to aid much further unfortunately, sorry
b
Well to know that you can successfully import that wasm in a normal Worker is an enormous north star so thank you.
and regarding Resvg in your worker, are importing like this?:
Copy code
import { Resvg, initWasm } from '@resvg/resvg-wasm';
import resvgwasm from '@resvg/resvg-wasm/index_bg.wasm'
j
Yeah, it was the example one I used in fact in a recent wasm import DX improvement I did, so I'm pretty familiar with it, haha:
yep, pretty much exactly this
b
@James So setup a separate worker. Having problems :
Copy code
import { Resvg, initWasm } from '@resvg/resvg-wasm';
import resvgwasm from '@resvg/resvg-wasm/index_bg.wasm'

export default {
    async fetch(request: Request): Promise<Response> {

    const reqBody = await request.text(); 

    await initWasm(resvgwasm)

    const resvg = new Resvg(reqBody, {
      fitTo: {
        mode: 'width',
        value: 1200
      }
    });
    const image = resvg.render();

    return new Response(image.asPng(), {
      headers: {
        'content-type': 'image/png'
      }
    });
    },
};
I get an error :
Copy code
[wrangler:err] AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:

  (0, import_assert5.default)(prepareStackTrace !== void 0)

    at getSourceMapper (C:\Users\...\node_modules\miniflare\dist\src\index.js:5749:30)
This is my first time using a standalone worker, a wasm, and resvg
It's importing the wasm module fine, but ...uh how did you use it? cuz Resvg's docs say to the
@resvg/resvg-wasm/index.js
file to use the Resvg constructor and to initiate the wasm. If you have experience using this, what did you do?
j
Copy code
typescript
import { Resvg, initWasm } from '@resvg/resvg-wasm';

function wasmInit(wasm: WebAssembly.Module) {
    return initWasm(wasm).catch((err) => {
        if ('message' in err && err.message?.startsWith?.('Already initialized')) {
            return;
        }
        throw err;
    });
}


// and then inside a request handler:
const { default: resvgwasm } = await import('@resvg/resvg-wasm/index_bg.wasm');
await wasmInit(resvgwasm);
const resvg = new Resvg(svgString, {
    fitTo: {
        mode: 'width',
        value: 512,
    },
});
const pngData = resvg.render();
const pngBuffer = pngData.asPng();
const response = new Response(pngBuffer, {
    headers: {
        'content-type': 'image/png',
    },
});
very similar to what you have, though I async loaded the wasm file
The error you're seeing there is a current bug with wrangler and is unfortunately swallowing errors for you: https://github.com/cloudflare/workers-sdk/pull/4719
b
Ok well I'm assuming your code is working but I have other code problems. I'm assuming you're using this as a dynamic opengraph image generator right? if it's going into a meta tag, it has to be a url as far as I know, so how are you passing an SVG into the worker? putting the SVG would be too big for a search param, and I cant put satori into the worker because it exceeds the script limit on the worker.
between satori and font buffers required for satori, I don't see how this would work. I really appreciate your time @James
j
I'm using it more to convert from SVG data I generate for QR codes, like at https://qrcodes.tools/, and then converting to PNG
so I already have the SVG I need
b
oh I see. Using a smaller svg would make this doable probably. Think this is the nail in the coffin then
j
https://developers.cloudflare.com/browser-rendering is in beta, but perhaps trying to render as HTML first might work better for your use-case? I'm not sure
I think others have got satori to work in a Worker though, hmm lemme see
Perhaps this repo might be helpful? https://github.com/kvnang/workers-og
Workers can be up to 10MB in size now, so Satori should be able to work fine
b
? for me it says it can't exceed 1MB gzipped
j
where do you see that? Pages build log? Ignore that
Oh you do need to be on paid for 10MB
b
Dude that worked!!! https://github.com/kvnang/workers-og Whatever magic they did to fit these all into the work under 1MB is magical. It's working as I intended to!
Thank you James!
j
amazing!! 😄
4 Views