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

在Expo React Native中离线运行含.wasm的Stockfish国际象棋引擎

在Expo React Native中离线运行Stockfish WASM引擎的解决方案

核心问题分析

你的当前代码基于浏览器DOM API(document.createElement、document.body.appendChild),但React Native(包括Expo)没有浏览器环境的DOM对象,所以这段代码在RN原生环境中根本无法执行——这是导致失败的主要原因,而非库的选择问题。

库的适用性判断

  • react-native-react-bridge:不适用。它的作用是在RN与WebView之间桥接React组件,并非用于处理WASM文件或浏览器环境的JS代码。
  • react-native-webassembly:适用。它专门用于在RN原生环境中加载和运行WASM模块,但需要处理Expo的资源路径问题。
  • 更推荐的方案:使用Expo WebView包裹现有HTML/JS代码。因为你已经有能在浏览器中正常运行的Stockfish实现,WebView提供了完整的浏览器环境,无需大幅修改代码,成本最低。

方案一:WebView快速迁移(推荐)

步骤1:整理资源文件

将Stockfish相关文件(stockfish.js、chess.min.js、stockfish.wasm)和你的HTML测试文件放到Expo项目的assets/stockfish目录下。

步骤2:修改HTML代码,添加RN通信逻辑

在HTML中,将原本的console.log输出替换为向RN发送消息的代码,以便在RN界面显示日志:

<!-- assets/stockfish/index.html -->
<!DOCTYPE html>
<html>
<head>
  <script src="./chess.min.js"></script>
  <script src="./stockfish.js"></script>
</head>
<body>
  <script>
    const sf = Stockfish();
    sf.onmessage = function(event) {
      // 将Stockfish的输出发送给RN
      window.ReactNativeWebView.postMessage(`Stockfish: ${event.data}`);
    };
    sf.postMessage('uci'); // 初始化引擎
    window.ReactNativeWebView.postMessage('Stockfish引擎已加载');
  </script>
</body>
</html>

步骤3:RN组件中加载WebView并接收日志

先安装依赖:

npx expo install expo-webview expo-asset

然后编写RN组件:

import React, { useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { WebView } from 'expo-webview';
import { Asset } from 'expo-asset';

export default function StockfishScreen() {
  const [logMessages, setLogMessages] = useState([]);

  // 获取本地HTML文件的URI
  const htmlAsset = require('./assets/stockfish/index.html');
  const htmlUri = Asset.fromModule(htmlAsset).uri;

  // 接收WebView传来的日志
  const handleMessage = (event) => {
    const newLog = event.nativeEvent.data;
    setLogMessages(prev => [...prev, newLog]);
  };

  return (
    <View style={styles.container}>
      {/* 隐藏WebView,只显示日志;调试时可去掉hidden样式 */}
      <WebView
        source={{ uri: htmlUri }}
        onMessage={handleMessage}
        javaScriptEnabled={true}
        domStorageEnabled={true}
        style={styles.hiddenWebView}
      />
      {/* 日志显示区域 */}
      <View style={styles.logContainer}>
        {logMessages.map((msg, idx) => (
          <Text key={idx} style={styles.logText}>{msg}</Text>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  hiddenWebView: { height: 0, width: 0 },
  logContainer: { flex: 1, padding: 10, backgroundColor: '#f5f5f5' },
  logText: { fontSize: 14, marginVertical: 2, color: '#333' }
});

方案二:原生RN环境加载WASM

如果需要完全脱离WebView,可使用react-native-webassembly:

步骤1:安装依赖

npm install react-native-webassembly
npx expo install expo-file-system expo-asset

步骤2:加载并运行WASM

import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as FileSystem from 'expo-file-system';
import { Asset } from 'expo-asset';
import { load } from 'react-native-webassembly';

export default function StockfishScreen() {
  const [logMessages, setLogMessages] = useState([]);

  useEffect(() => {
    const loadStockfish = async () => {
      try {
        // 将WASM文件从assets复制到RN可访问的文档目录
        const wasmAsset = require('./assets/stockfish/stockfish.wasm');
        const wasmAssetUri = Asset.fromModule(wasmAsset).uri;
        const destUri = `${FileSystem.documentDirectory}stockfish.wasm`;
        await FileSystem.copyAsync({ from: wasmAssetUri, to: destUri });

        // 加载WASM模块
        const wasmInstance = await load(destUri);
        // 注意:Stockfish的WASM需要配合官方JS封装使用,需参考官方文档适配RN环境
        setLogMessages(prev => [...prev, 'WASM模块已加载']);
      } catch (err) {
        setLogMessages(prev => [...prev, `加载失败:${err.message}`]);
      }
    };

    loadStockfish();
  }, []);

  return (
    <View style={styles.container}>
      {logMessages.map((msg, idx) => (
        <Text key={idx} style={styles.logText}>{msg}</Text>
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, padding: 10, backgroundColor: '#f5f5f5' },
  logText: { fontSize: 14, marginVertical: 2, color: '#333' }
});

关键注意事项

  • Expo中访问assets文件必须通过expo-asset获取正确的URI,不能直接使用相对路径(如/stockfish/stockfish.js)。
  • RN原生环境没有浏览器的window、document等对象,所有基于DOM的代码都无法直接运行。
  • 调试时可使用Expo的Debug模式查看RN的console日志,或在WebView中长按选择"Inspect"打开调试工具。

内容的提问来源于stack exchange,提问作者Muhammad Hamza Latif

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:53:18