如何在Create React App中使用public文件夹内的WASM脚本?
解决Create React App中无需eject即可使用WASM的方案
我完全懂你的痛点——用wasm-pack生成的WASM代码丢src里被webpack乱处理报错,又不想eject去折腾一堆webpack配置。把代码放public目录绝对是个聪明的思路,下面就一步步教你怎么在React组件里正确导入并调用这些WASM函数:
第一步:把WASM文件放到public目录
先把wasm-pack生成的pkg文件夹里的所有文件(比如your_crate_bg.wasm、your_crate.js、your_crate.d.ts这些)复制到Create React App项目的public/wasm目录下(没有wasm文件夹就新建一个)。这样webpack会原封不动把这些文件打包到最终的构建产物里,不会对它们做任何转译或干扰处理。
第二步:在React组件中动态加载并调用WASM
因为public目录下的文件不能直接用import导入,我们需要通过动态创建script标签的方式加载wasm-pack生成的包装JS,然后访问全局对象来调用WASM函数:
import { useEffect, useState } from 'react'; function WasmDemo() { const [wasmApi, setWasmApi] = useState(null); useEffect(() => { // 动态创建script标签加载WASM包装JS const script = document.createElement('script'); // 路径对应public下的文件位置,这里假设你放到了public/wasm/your_crate.js script.src = '/wasm/your_crate.js'; script.onload = async () => { // wasm-pack生成的包装JS通常会把模块挂在window上,名字就是你的crate名 // 调用默认的init函数初始化WASM,返回包含所有导出函数的对象 const initializedApi = await window.your_crate.default(); setWasmApi(initializedApi); }; script.onerror = (error) => { console.error('加载WASM包装文件失败:', error); }; document.body.appendChild(script); // 组件卸载时清理资源 return () => { document.body.removeChild(script); delete window.your_crate; }; }, []); const callWasmFunction = () => { if (wasmApi) { // 调用你在Rust里导出的函数,比如这里假设导出了一个add函数 const result = wasmApi.add(2, 3); alert(`WASM计算结果:${result}`); } }; return ( <div> {wasmApi ? ( <button onClick={callWasmFunction}>调用WASM加法函数</button> ) : ( <p>正在加载WASM模块...</p> )} </div> ); } export default WasmDemo;
额外提示(TypeScript用户)
如果你的项目用TypeScript,为了避免类型报错,可以在项目里声明全局模块类型:
declare global { interface Window { your_crate: { default: () => Promise<{ add: (a: number, b: number) => number; // 这里添加你所有导出的WASM函数类型 }>; }; } } // 确保这个文件被视为模块 export {};
关键原理说明
Create React App的webpack配置默认会把src目录下的所有文件当作源码处理,包括转译、tree-shaking等操作,而WASM文件和它的包装JS并不适合这套流程。把文件放到public目录后,webpack会直接将它们复制到构建产物的根目录,完全保留原始内容,这样浏览器就能正确加载并执行WASM代码了。
内容的提问来源于stack exchange,提问作者Richard Rast
相关产品推荐
相关产品推荐

