jamsinclair / jSquash

Browser & Web Worker focussed wasm bundles derived from the Squoosh App.
Apache License 2.0
222 stars 14 forks source link

Failed to work in cloudflare workers esm mode #20

Closed rwv closed 1 year ago

rwv commented 1 year ago
// @ts-ignore
import PNG_DEC_WASM from '../../node_modules/@jsquash/png/codec/squoosh_png_bg.wasm';
// @ts-ignore
import WEBP_ENC_WASM from '../../node_modules/@jsquash/webp/codec/enc/webp_enc_simd.wasm';

await initPngWasm(PNG_DEC_WASM);
const imageData = await decodePng(buffer);

await initWebpWasm(WEBP_ENC_WASM);
const webpBuffer = await encodeWebp(imageData); // error happens here

error:

TypeError: Cannot read properties of undefined (reading 'href')
    at index.js:369:45
    at initEmscriptenModule (index.js:3278:10)
    at init (index.js:3293:24)
    at async encodeImageToWebp (index.js:3454:25)
    at async index.js:3504:26
    at async handle (index.js:86:34)
    at async Object.handle (index.js:86:34) {
  stack: TypeError: Cannot read properties of undefined (re…6:34)
    at async Object.handle (index.js:86:34),
  message: Cannot read properties of undefined (reading 'href')
}

After some investigating, this may be related to https://github.com/jamsinclair/jSquash/blob/1edfc086e22b6aa01910cff5fd20826cf9e3dfa2/packages/webp/codec/enc/webp_enc.js which access this.location.href

rwv commented 1 year ago

workaround:

return moduleFactory({
  // Just to be safe, don't automatically invoke any wasm functions
  noInitialRun: true,
  instantiateWasm,
  locateFile: (url: string) => {
    return url;
  },
});
jamsinclair commented 1 year ago

Thanks for reporting this @rwv, I've published a new version that I think will fix this.

Can you try npm install -S @jsquash/webp@1.2.0 and see if that resolves the issue?

rwv commented 1 year ago

Thank you! I haven’t try yet. But I found an issue in example that Cloudflare workers ESM mode spent not support wasm in wrangler.toml anymore.

Use direct import instead

// @ts-ignore import PNG_DEC_WASM from '../../node_modules/@jsquash/png/codec/squoosh_png_bg.wasm'; // @ts-ignore import WEBP_ENC_WASM from '../../node_modules/@jsquash/webp/codec/enc/webp_enc_simd.wasm';

rwv commented 1 year ago

Maybe you could mention that in readme.md

jamsinclair commented 1 year ago

Thanks for the feedback! Once I confirm I'll add. It seems to working for me locally with wrangler v3 but perhaps I am not properly in ESM mode.

jamsinclair commented 1 year ago

Ah I see the ESM mode is very different from the Service worker mode. I'll need to make additional changes.

Apologies I misunderstood the problem.

rwv commented 1 year ago

Maybe you can import wasm directly in jSquash package and user don’t have to run initWASM manually. Although this may affect current users.

jamsinclair commented 1 year ago

It looks like my previous changes still work with the ESM Format 🙌

Thanks for your suggestions @rwv

Maybe you can import wasm directly in jSquash package and user don’t have to run initWASM manually.

Unfortunately I don't think we can. You cannot import "wasm" files directly in JavaScript. Cloudflare is cheating a little bit by allowing non-JS files to be imported, like wasm and html with their bundler. This improves the developer experience but makes the files invalid JavaScript files.

If you don't mind, I'll close this issue now. If you're still encountering issues feel free to re-open. Thanks again!