Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wasm): universal support with esm import syntax #2017

Merged
merged 6 commits into from
Dec 21, 2023
Merged

Conversation

pi0
Copy link
Member

@pi0 pi0 commented Dec 21, 2023

πŸ”— Linked issue

❓ Type of change

  • πŸ“– Documentation (updates to the documentation, readme, or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

This PR unifies WASM support using Nitro's built-in wasm plugin and simplified ESM import syntax: (Following ES Module Integration Proposal for WebAssembly)

Using dynamic imports:

export default defineLazyEventHandler(async () => {
  const { sum } = await import("~/wasm/sum.wasm");
  return eventHandler(() => {
    return `2+3=${sum(2, 3)}`;
  });
});

Using static imports: (1)

import { sum } from "~/wasm/sum.wasm";

export default eventHandler(() => {
  return `2+3=${sum(2, 3)}`;
});
  • On Node.js and platforms yet not supporting native .wasm imports, Nitro by default creates a base64 inlined version (in a chunk) and instantiates the module
  • On supported platforms (Cloudflare pages and modules), plugin will use native wasm import and copy the asset to output

(1) One of the main blockers, are worker targets that don't support top level await, combined with rollup limitation with inlineDynamicImports we cannot use top level await for await WebAssembly.instantiate. This mainly affects/breaks Vercel Edge target. Internally we support wasm.lazy flag that causes to avoid depending on top-level wait for maximise compatibility. It requires static import slight syntax change to work universally again:

import _mod from "~/wasm/sum.wasm";

export default eventHandler(async () => {
  const { sum } = await _mod;
  return `2+3=${sum(2, 3)}`;
});

The value of _mod is a virtual Promise-like that lazily get's evaluated. Hopefully at some point we don't require this syntax change too.

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@pi0 pi0 requested a review from antfu December 21, 2023 20:51
@pi0 pi0 mentioned this pull request Dec 21, 2023
@pi0 pi0 marked this pull request as ready for review December 21, 2023 21:53
@pi0
Copy link
Member Author

pi0 commented Dec 21, 2023

Merging to make it testable via edge-channel. Feedbacks more than welcome specially @antfu @harlan-zw since I know you have some good projects to verify against.

@pi0 pi0 merged commit c40a3bd into main Dec 21, 2023
5 checks passed
@pi0 pi0 deleted the feat/wasm-inline branch December 21, 2023 21:54
@pi0
Copy link
Member Author

pi0 commented Dec 21, 2023

Early checking against shikiji, seems some issues

@antfu
Copy link
Collaborator

antfu commented Dec 21, 2023

Looks awesome! Will give a try tmr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants