如何在Next.js中导入WebAssembly并调用Rust编译的Board结构体
在Next.js中正确调用wasm-pack生成的WebAssembly代码的解决方案
问题背景
已将wasm-pack build生成的pkg目录内容复制到嵌套在Rust库项目内的Next.js项目public文件夹中,但无法正确调用WebAssembly文件实现棋盘绘制。
Rust项目配置
[package] name = "chess" version = "0.1.0" edition = "2021" [lib] crate-type=["cdylib"] [dependencies] wasm-bindgen="0.2" js-sys="0.3.45" [dependencies.web-sys] version = "0.3.69" features = [ "Window", "Document", "HtmlCanvasElement", "CanvasRenderingContext2d", "Element", "Node", "Event", "MouseEvent" ]
Rust核心代码
use wasm_bindgen::prelude::*; #[wasm_bindgen] pub struct Board{ width: i32, height: i32, } #[wasm_bindgen] impl Board { pub fn init(x: i32, y: i32) -> Board { Board { width: x, height: y, } } pub fn draw(&self, canvas: web_sys::CanvasRenderingContext2d) { canvas.set_fill_style(&JsValue::from_str("black")); canvas.set_stroke_style(&JsValue::from_str("white")); let size: f64 = 64.0; for i in 0..self.width { for j in 0..self.height { let x: f64 = i as f64; let y: f64 = j as f64; canvas.fill_rect(x*size, y*size, size, size); canvas.stroke_rect(x*size-5.0, y*size-5.0, size-10.0, size-10.0); } } } }
期望的JS调用逻辑
// 获取canvas元素和2D上下文 const canvas = document.getElementById('canvas'); const context = canvas.getContext('2d'); // 创建宽高为10的Board实例 const board = Board.init(10, 10); // 调用draw方法绘制棋盘 board.draw(context);
解决步骤
1. 调整wasm-pack编译目标
Next.js属于浏览器环境,编译时需指定目标为web:
wasm-pack build --target web
编译完成后,将pkg目录下所有文件(包括chess.js、chess_bg.wasm、chess.d.ts等)复制到Next.js项目的public/wasm子目录中(单独归类便于管理)。
2. 在Next.js客户端组件中加载Wasm
Next.js服务端组件无浏览器环境,必须在客户端组件中加载Wasm。创建客户端组件(如components/ChessBoard.tsx):
'use client'; import { useEffect, useRef } from 'react'; export default function ChessBoard() { const canvasRef = useRef<HTMLCanvasElement>(null); useEffect(() => { const loadWasm = async () => { // 加载Wasm模块 const chessModule = await import('/wasm/chess.js'); await chessModule.default(); // 初始化Wasm实例 const canvas = canvasRef.current; if (!canvas) return; const context = canvas.getContext('2d'); if (!context) return; // 设置canvas尺寸适配棋盘 canvas.width = 640; canvas.height = 640; // 创建Board实例并执行绘制 const board = chessModule.Board.init(10, 10); board.draw(context); }; loadWasm(); }, []); return <canvas ref={canvasRef} />; }
3. 关键注意事项
- 无需修改
chess.js中的Wasm路径:默认会从同目录加载chess_bg.wasm,放在public/wasm下可自动匹配路径。 - 类型支持:可将
chess.d.ts复制到项目中,或在tsconfig.json中添加类型引用以获得TS类型提示。 - 必须使用客户端组件:添加
'use client'指令,确保代码在浏览器环境执行。
内容的提问来源于stack exchange,提问作者hacker man
相关产品推荐
相关产品推荐

