最速でWeb Assemblyを使ったweb pageを試す
動かし方
1. 適当なdirectoryで↓を実行する
要wasm-pack
code:sh
2. 同じdirectoryで↓を実行する
code:sh
3. 出力されたURLを押す
code:script.tsx
const app = createApp();
// メインのHTMLファイルを返す
app.handle("/", async (req) => {
await req.respond({
status: 200,
headers: new Headers({
"content-type": "text/html; charset=UTF-8",
}),
body: ReactDOMServer.renderToString(
<html>
<head>
<meta charSet="utf-8" />
<title>Web page demo</title>
<script type="module" src="./index.js" />
</head>
<body></body>
</html>
),
});
});
// index.jsを返す
app.get("/index.js", async (req) => {
await req.respond({
status: 200,
headers: new Headers({
"content-type": "application/javascript; charset=UTF-8",
}),
body: await Deno.readTextFile('index.js'),
});
});
// pkg/にあるファイルを返す
app.get(/^\/pkg/, async (req) => {
await req.respond({
status: 200,
headers: new Headers({
"content-type": contentType( lookup(.${req.path}) ?? "text/plain") ?? "text/plain; charset=UTF-8",
}),
body: await Deno.readTextFile(.${req.path}),
});
});
const port = 8888;
app.listen({ port });
console.log(go to http://localhost:${8888});
改変
code:index.js
import {wasm} from './pkg/web_page_demo_bg.wasm.js';
import init, { add } from './pkg/web_page_demo.js';
(async () => {
await init(wasm); // wasmを読み込む
// 読み込んだ函数を使う
const result = add(1, 2);
console.log(1 + 2 = ${result});
if (result !== 3) throw new Error("wasm addition doesn't work!");
})();
RustのcodeをWeb Assemblyにするbuild script
code:build.ts
// 必要なファイルをdownloadする
{
const filename = 'lib.rs';
await ensureFile(./src/${filename});
const res = await fetch(${entry}/${filename});
await Deno.writeTextFile(./src/${filename}, await res.text());
}
{
const filename = 'Cargo.toml';
await ensureFile(filename);
const res = await fetch(${entry}/${filename});
await Deno.writeTextFile(filename, await res.text());
}
{
const filename = 'index.js';
await ensureFile(filename);
const res = await fetch(${entry}/${filename});
await Deno.writeTextFile(filename, await res.text());
}
// compileを実行する
await exec('wasm-pack build --target web --release', {output: OutputMode.Capture, verbose: true});
// 予めUint8Arrayにしておく
const wasm = await Deno.readFile("./pkg/web_page_demo_bg.wasm");
await Deno.writeTextFile("./pkg/web_page_demo_bg.wasm.js",
export const wasm = new Uint8Array([${wasm.join(",")}]););
Web AssemblyにするRust code
code:lib.rs
use wasm_bindgen::prelude::*;
// Called when the wasm module is instantiated
pub fn main() -> Result<(), JsValue> {
// Use web_sys's global window function to get a handle on the global
// window object.
let window = web_sys::window().expect("no global window exists");
let document = window.document().expect("should have a document on window");
let body = document.body().expect("document should have a body");
// Manufacture the element we're gonna append
let val = document.create_element("p")?;
val.set_inner_html("Hello from Rust!");
body.append_child(&val)?;
Ok(())
}
pub fn add(a: u32, b: u32) -> u32 {
a + b
}
Rust用project setting
改変してある
code:Cargo.toml
name = "web-page-demo"
version = "0.1.0"
edition = "2021"
wasm-bindgen = "0.2.73"
version = "0.3.4"
features = [
'Document',
'Element',
'HtmlElement',
'Node',
'Window',
]