You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:53:09