Our great sponsors
-
SurveyJS
Open-Source JSON Form Builder to Create Dynamic Forms Right in Your App. With SurveyJS form UI libraries, you can build and style forms in a fully-integrated drag & drop form builder, render them in your JS app, and store form submission data in any backend, inc. PHP, ASP.NET Core, and Node.js.
Myself and three others have been working on a tool called Allusion in our spare time: A free image organization application built for artists. It runs in Electron as a ReactJS application. One of its key components is the image gallery. Since users may import thousands of images, we can't just render them all using pure HTML and CSS. Over the course of the development, we tried out several out-of-the-box ReactJS packages (mainly react-window and react-virtualized but none really suited our needs - be it their design or performance. In the end, we wrote our own super slick image gallery from scratch. It turned out quite nice, so I wanted to share our findings.
Rust was was something I wanted to get into for a while already, and it's a natural fit for WASM modules. The module is set-up with wasm-pack which outputs your WASM file along with TypeScript definitions as an easily importable ES6 module.
Even though the computation only takes less than a millisecond on my machine, it might not on low-end devices or under heavy load. By computing the layout in a WebWorker, it won't interrupt the main UI thread, meaning that the application will stay responsive. We opted for setting up a WebWorker using com-link, mainly for its ease of use. We don't want to copy the memory buffer every time a message is sent from the worker. Figuring out how to set up shared memory between the WASM memory in the worker and the main thread was the biggest time sink of this adventure. At first we sent the buffer as a Transferrable but this stopped working in a recent release of Chrome. Instead, we configure the WASM memory to become a SharedArrayBuffer, which has the same capability. This is not supported out of the box: follow this guide to learn more.
The final implementation: Masonry algorithm in Rust, Webworker, Masonry renderer which makes use of the Virtualized renderer