iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💭

Using Svelte, WebAssembly, TypeScript, and Rollup: The Rust Journey (5)

に公開

The Problem of Too Many Elements

Related Articles:

Past Articles in the "Rust Conquers" Series

In the previous article, we connected TypeScript, rollup.js, and WebAssembly.
Next, let's connect it with a frontend framework.

While we could have used Yew for the frontend, Rust—which requires a bit of extra effort just to get running—doesn't pair well with the frontend, which also requires meticulous adjustments.
Therefore, I chose a JavaScript framework.
However, I'm already tired of Vue and React, so I'll use Svelte, which has been a hot topic recently.

Svelte is a tool for building fast web applications.
It is similar to JavaScript frameworks such as React and Vue, which share a goal of making it easy to build slick interactive user interfaces.
But there's a crucial difference: Svelte converts your app into ideal JavaScript at build time, rather than interpreting your application code at run time. This means you don't pay the performance cost of the framework's abstractions, and you don't incur a penalty when your app first loads.
You can build your entire app with Svelte, or you can add it incrementally to an existing codebase. You can also ship components as standalone packages that work anywhere, without the overhead of a dependency on a conventional framework.
Svelte

It is essentially Vue with the concept of Virtual DOM removed.
It is said that the amount of code is smaller compared to the other two.

Since writing everything from scratch would make this article too long, I will use a template this time.

ヾ(・ω<)ノ" 三三三● ⅱⅲ Roll, roll♪

------------------- ↓ The main topic starts here ↓-------------------

Prerequisites

This assumes that Rust and Node.js are up and running.
Please refer to the previous articles.
You are good to go if you can execute the following commands.

cargo --version
npm --verion
rustup target add wasm32-unknown-unknown
cargo install cargo-edit

Creating a project from the Svelte template

I will use a template that runs Svelte builds using rollup.js.

By default, it is configured for JavaScript, but there is a script provided to replace it with TypeScript.
Since the versions of the packages used are also old, I will reconfigure them to newer ones.

npx degit sveltejs/template svelte-wasm
cd svelte-wasm
node ./scripts/setupTypeScript.js
npx npm-check-updates -u
npm i -D @wesley-clements/rollup-plugin-raw-wasm
npm run dev

(・∀・) Easy, right!!

Adjusting rollup.js configuration

Before building WebAssembly, I will adjust the rollup.js configuration.
Add the wasm loader installed via npm to the configuration.

./rollup.config.js
import css from 'rollup-plugin-css-only';
+ import { rawWasm } from "@wesley-clements/rollup-plugin-raw-wasm"

const production = !process.env.ROLLUP_WATCH;
・・・
typescript({
  sourceMap: !production,
  inlineSources: !production
}),
+ rawWasm({
+   publicPath: '/build/'
+ }),

// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),

Preparing the WebAssembly module

Set up the Rust source code using the cargo command.

cargo init --lib
printf '[lib]\ncrate-type = ["cdylib", "rlib"]' | tee -a ./Cargo.toml
cargo add wasm-bindgen js-sys

Implementation

./src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn sum_numbers(numbers: &[i32]) -> i32 {
    numbers.iter().sum()
}

Build

wasm-pack build --target web --release --out-name svelte-wasm

Implementing WebAssembly on the Svelte side

Source Code

Since WebAssembly basically needs to be called via asynchronous processing, I will change everything to be asynchronous.

./src/main.ts
import App from './App.svelte'
import init, {sum_numbers} from "../pkg/svelte-wasm.js"
import path from "../pkg/svelte-wasm_bg.wasm"

const app = (async () => {
  await init(path)
  const app = new App({
    target: document.body,
    props: {
      name: 'world',
      sum_numbers,
    }
  })
})()
export default app;

View side

./src/App.svelte
<script lang="ts">
  export let name: string;
+ export let sum_numbers: Function;
+ const sum = sum_numbers(new Int32Array([5,60,300]))

</script>

<main>
-  <h1>Hello {name}!</h1>
+  <h1>Hello {name} {sum}!</h1>
  <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>

Execution

npm run dev

(・∀・)(・∀・)Yeah!!!!

The frontend configuration is now finalized.

------------------- ↓ Postscript starts here ↓-------------------

Why didn't you use esbuild?

Chronologically, this article came first, but I have already published the following article.

https://zenn.dev/dozo/articles/54f697ff41f100

Since things get complicated when there are too many elements, I have omitted the description regarding esbuild in this article.

Discussion