引入wasm-bindgen的React-TS项目运行Jest测试报语法错误如何解决
React+TS项目引入Rust/Wasm时Jest测试报错修复方案
问题现象
在引入Rust编译产出的Wasm依赖库的React-TypeScript项目中,开发、生产环境前端运行正常,但执行Jest测试时先后出现两类报错。
第一阶段报错
直接执行测试命令时,Jest无法识别Wasm库的ESM导出语法:
/workspace/react-jest-rust/node_modules/rust-wasm-lib/index.js:73 export function message(s) { ^^^^^^ SyntaxError: Unexpected token 'export'
拉取示例项目后执行yarn test a即可复现该问题。
首次修复后的新报错
在package.json中添加如下配置,让Jest转译node_modules下的Wasm库,解决初始的export语法报错:
"jest": { "transformIgnorePatterns": [ "node_modules/(?!rust-wasm-lib)/" ] }
重新执行测试命令后,出现import.meta相关语法错误:
/big/workspace/sequent/react-jest-rust/node_modules/rust-wasm-lib/index.js:125 input = new URL('index_bg.wasm', import.meta.url); ^^^^ SyntaxError: Cannot use 'import.meta' outside a module 2 | import logo from './logo.svg'; 3 | import './App.css'; > 4 | import init, {test} from 'rust-wasm-lib'; | ^
根因分析
报错的核心原因有两点:
- Jest默认运行在CommonJS环境,不会转译node_modules下的文件,因此无法识别Wasm绑定代码的ESM格式
export语法 - wasm-bindgen默认生成的ESM绑定代码使用
import.meta.url拼接Wasm文件路径,该语法无法在CommonJS模式下的Jest运行时被解析
完整修复步骤
- 安装所需开发依赖:
如果是使用create-react-app创建的项目,上述依赖通常已预装,可跳过此步。yarn add -D @babel/core @babel/preset-env babel-jest - 调整
package.json中的Jest配置,在原有transformIgnorePatterns基础上补充转译规则和静态资源mock规则:"jest": { "transformIgnorePatterns": [ "node_modules/(?!rust-wasm-lib)/" ], "transform": { "^.+\\.(t|j)sx?$": "babel-jest", "^.+\\.wasm$": "<rootDir>/test/wasm-transform.js" }, "moduleNameMapper": { "\\.(css|less|svg|png|jpg)$": "<rootDir>/test/empty-mock.js" } } - 在项目根目录新建
test文件夹,在文件夹内创建wasm-transform.js,自定义Wasm文件的转译逻辑:const fs = require('fs'); module.exports = { process(source, file) { const wasmContent = fs.readFileSync(file); return `module.exports = Buffer.from(${JSON.stringify(wasmContent.toString('base64'))}, 'base64');`; } }; - 在同一
test文件夹下创建empty-mock.js,mock测试中不需要实际加载的静态资源:module.exports = {}; - 在项目根目录新建
babel.config.json,配置Babel转译规则,替换不兼容的import.meta语法:{ "presets": [ ["@babel/preset-env", { "targets": { "node": "current" } }] ], "plugins": [ () => ({ visitor: { MetaProperty(path) { path.replaceWithSourceString('{ url: require("url").pathToFileURL(__filename).href }'); } } }) ] } - 在测试文件中,所有用例执行前先调用Wasm库的init方法完成初始化:
import init, { test } from 'rust-wasm-lib'; beforeAll(async () => { await init(); }); test('rust wasm function runs correctly', () => { expect(test()).not.toBeNull(); });
注意:如果Wasm库初始化时提示找不到Wasm文件,可以在调用init()时直接传入transform返回的Buffer实例,绕过路径解析逻辑。
配置完成后重新执行yarn test a即可正常运行测试。
内容的提问来源于stack exchange,提问作者DonDrapper
相关产品推荐
相关产品推荐

