Menci / vite-plugin-wasm

Add WebAssembly ESM integration (aka. Webpack's `asyncWebAssembly`) to Vite and support `wasm-pack` generated modules.
MIT License
281 stars 16 forks source link

fix: wasm functions return undefined #11

Closed sigoden closed 1 year ago

sigoden commented 2 years ago

This pr solve #1.

Why some wasm functions return undefined?

If you import a wasm js module:

import { parse } from "@jsona/openapi";
console.log(parse("{}"));

vite will compile this to:

import { parse } from "/node_modules/@jsona/openapi/index_bg.js?v=bb17ff0c"; 

NOTE: vite append a version hash to module path.

vite-wasm-plugin will resolve this to:


import __vite__initWasm from "/__vite-plugin-wasm-helper"
import { __wbindgen_json_parse as __vite__wasmImport_0_0 } from "/node_modules/@jsona/openapi/index_bg.js";
const __vite__wasmModule = await __vite__initWasm({ "./index_bg.js": { __wbindgen_json_parse: __vite__wasmImport_0_0 } }, "/node_modules/@jsona/openapi/index_bg.wasm?init");
export const memory = __vite__wasmModule.memory;
export const parse = __vite__wasmModule.parse;
export const __wbindgen_malloc = __vite__wasmModule.__wbindgen_malloc;
export const __wbindgen_realloc = __vite__wasmModule.__wbindgen_realloc;

vite-wasm-plugin imports the importer module /node_modules/@jsona/openapi/index_bg.js without a version hash.

That's the problem. They are two different modules because their paths are different.

If you run non-local wasm js module(vite don't add version hash to non-node_module files), call a function depends on __wbindgen* function, it will return undefined.

Menci commented 2 years ago

Could you add some test that fails without this PR and passes with it? I personally couldn't reproduce this issue.

sigoden commented 2 years ago

This happend in dev mode, I'm afraid the tests need to be refactored.

Files to reproduce this issue.

package.json

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@jsona/openapi": "^0.2.1",
    "vite": "^3.1.0",
    "vite-plugin-wasm": "^2.1.0",
    "vite-plugin-top-level-await": "^1.1.1"
  }
}

vite.config.js

import { defineConfig } from "vite";
import wasm from "vite-plugin-wasm";
import topLevelAwait from "vite-plugin-top-level-await";

export default defineConfig({
  plugins: [
    wasm(),
    topLevelAwait(),
  ]
})

index.html

<body>
  <script type="module" src="/main.js"></script>
</body>

main.js

import { parse } from "@jsona/openapi";
console.log(parse("{}"));
Menci commented 1 year ago

I merged your code with latest main changes and added unit test. Some circular dependency happened in @syntect/wasm was found. Could you please check the error?

sigoden commented 1 year ago

https://github.com/vitejs/vite/pull/10141 fix version query.

The easiest way to fix this problem now is to exclude wasm js module from pre-bundling (vite >= 3.1.2)

  optimizeDeps: {
    exclude: [
      "@jsona/openapi"
    ]
  },

In order to solve this problem perfectly, vite needs to provide api reverse lookup importer.