SvelteKit + WasmPack is unusable
Using the production command of SvelteKit deno run build will break the WASM imports. It produces a compiled JS bundle, but it moves the src_wasm_bg.wasm into assets folder, while the compiled logic is looking for it in _app/immutable/chunks where the rest of compiled JS is.
(src_wasm is the name of my rust crate)
http://localhost:1420/_app/immutable/chunks/src_wasm_bg.wasm
[HTTP/1.1 404 Not Found 5ms]
It also produces the following error. When I tried to bypass this by manually importing the WASM from the assets folder, it got blocked due to incorrect MIME types, similarly to the error below.
`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:
TypeError: WebAssembly: Response has unsupported MIME type '' expected 'application/wasm'
During the build process the following notice is also produced:
new URL('src_wasm_bg.wasm', import.meta.url) doesn't exist at build time, it will remain unchanged to be resolved at runtime. If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.
No matter what I do, I was unable to get WASM to work in production ready environment in SvelteKit. In dev mode it works fine though.
The same errors are produced by both the node and static adapters.
Am also having these issues. Did you ever find a fix?
Am also having these issues. Did you ever find a fix?
@Br3nnabee
I ditched this package and I was able to get my compiled wasm-pack output working with a different library called vite-plugin-wasm instead.
First you need to allow vite to load your output from wasmpack (or you can put it in node_modules instead)
vite.config.ts
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import wasm from "vite-plugin-wasm";
import topLevelAwait from "vite-plugin-top-level-await";
export default defineConfig({
plugins: [sveltekit(), wasm(), topLevelAwait()],
server: {
fs: {
allow: ['./src-wasm/pkg'],
},
}
});
Then import it in your svelte file and initialize it.
import * as wasmlib from "../../src-wasm/pkg"
onMount(() => {
wasmlib.default();
});
Then you can use it
output = wasmlib.my_function("hello_world");
This library does work when you build the app, so that's good.
after migrating a version 4 sveltekit app to svelte 5, i was seeing issues in prod with 404s trying to pull down the wasm files similar to the OP
i figured to update the wasm-pack lib from v0.11 to v0.13, but then started receiving more errors. with it still installed i reverted back to v4 svelte and still had errors. Once i swapped back to svelte 4 and wasm-pack v0.11 my app worked fine.
im assuming some compatibility issues with newer vite (svelte 5), wasm-pack, and this vite-plugin-wasm-pack.
I have had zero issues with this plugin (many thanks) and don't want to swap out @IDEDARY but i may have to if I cannot resolve. Thanks for the alternative and investigation!!
I encountered the same problem as the OP today, and after searching and testing numerous threads/suggestions, none seem to provide a straightforward fix...
I do agree that the *_bg.wasm file should be bundled into _app/immutable/chunks/ where it would make sense, not somehow moved to the assets/ folder. But until it is fixed upstream (hopefully?), here is my workaround in SvelteKit.
__wbg_init(), the exported default, allows you to specify the path to the .wasm file. If the build output is predictable, which in this case, it is always in /assets/<yourlib>_bg.wasm, you can specify the path when calling the init function:
// In your .svelte file, or
// You can also add this in +layout.svelte if you want your wasm lib to be available in all subroutes
// Init your wasm lib like this
import __wbg_init from "src_wasm"; // or whatever the name of your wasm lib is (check your Cargo.toml)
onMount(() => { __wbg_init({ module_or_path: "/assets/src_wasm_bg.wasm" }); }); // please check your lib name :>
Then, to use it:
<!-- In your .svelte file, -->
<!-- if already called __wbg_init in +layout.svelte, you don't have to call it again -->
<script lang="ts">
import { greet, my_other_fn } from "src-wasm"; // make sure to match your wasm lib name
// Reactive variable that relies on wasm
let value: number | null = $state(null);
let wasmDerived: number | null = $derived.by(() => {
if (!value) {
return null;
}
return my_other_fn(value);
});
</script>
<button onclick={() => greet("Hi there")}>Test</button>
{wasmDerived}
I guess the benefit of this workaround is that it's just 2 lines in your +layout.svelte that can be updated easily later on if the bundler behavior changes?