-
Notifications
You must be signed in to change notification settings - Fork 49
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!: use Vite, Vitest; use Rust/WebAssembly instead of Asm.js #20
Conversation
Use Vite instead of Webpack as our build tool. Vite is considerably simpler and requires less configuration than Jest. We also need Vite to use Vitest, which provides better support for ESM and WebAssembly than Jest, and does not require a separate build setup.
Vitest integrates seamlessly with Vite, and supports ESM and WebAssembly much better than Jest.
Reimplement the image decoder, previously implemented in handwritten Asm.js, into Rust/WebAssembly. Since Asm.js is effectively a "done" technology and is unsupported by esbuild, moving to WebAssembly is a sensible choice. The new implementation is almost as fast as the previous one in Chrome. At build time, the WebAssembly binary is inlined into the bundle as a base64-encoded string. This allows downstream users to use regular bundlers. Due to how WebAssembly works, however, the library's signature has changed. Now, the library exports a `Promise` object named `init`. This promise is created when the library is imported, and is resolved asynchronously. Before using symbols exported by the library (including the default export), users must wait for the promise to resolve. example: import PSD, {init} from '@webtoon/psd' async fun() => { await init; PSD.parse(/* ... */) }
Bump the minimum browser versions (used by eslint-plugin-compat) to reflect WebAssembly support. Currently, the minimum browser versions include those that support: TextDecoder, Typed Arrays, WebAssembly
- Bump supported browser versions - Update bundle size (larger, but still smaller than competitiors) - Add info on async initialization and `init`
MotivationOne of our long-term goals has been using WebAssembly to improve image decoding performance. We initially implemented an asm.js decoder to explore possible performance gains. While we did see a reasonable improvement, we cannot continue to use asm.js for the following reasons:
These problems meant that we must adopt WebAssembly at some point; that is now. The following is a detailed explanation of this pull request. It's long, so hold tight. Note: This pull request depends on #19. Use Vite & Vitest instead of Webpack & JestVite is a modern build tool. It supports TypeScript and native ESM better than Webpack, and does not require as many plugins to work. It's also very fast for development builds. Vitest is a test framework which integrates well with Vite, and handles native ESM better than Jest. Migrate to Rust/WebAssemblyWe rewrote the asm.js decoder in Rust. This is compiled to WebAssembly using wasm-pack. The WASM binary is bundled into the build artifact ( When the library is imported, the WASM binary is decoded asynchronously, then the rest of the module is initialized. @webtoon/psd now exports a import PSD, {init} from '@webtoon/psd';
PSD.parse(/* ... */); // error, the library has not been initialized yet
(async () => {
await init; // Wait for the library to initialize itself
// Note that 'init' is NOT a function!
// await init() <-- this is invalid
PSD.parse(/* ... */);
})();
// If you can use top-level await, this becomes considerably simpler
await init;
PSD.parse(/* ... */);
// Since 'init' is added to the task queue when the library is imported,
// it should probably be loaded by the time an event handler fires.
// Thus, this should _probably_ be safe.
elem.addEventListener('someEvent', () => {
PSD.parse(/* ... */);
}) From now on, developers must install wasm-pack on their system to build @webtoon/psd. Preliminary testing indicates that the new WASM decoder performs comparably to the old decoder. In the future, we hope to gain further performance improvements. |
…locks-for-effects expose multipbleObjectBasedeffects and ObjectUndocumented
For the full story, see the second comment.
Summary of changes
For users
Await theNot needed once feat!: init WASM during decode, remove top-level init #24 is mergedinit
promise before using @webtoon/psd:For developers
rpm install
-ing this project will also install wasm-pack.