vite 和 webpack 项目使用wasm-pack 生成的 npm 包

背景

出于某些原因,把数据统计工作放到前端了,表格最多 20 万行,20 多列,需要计算:最大值、最小值、中位数、方差、标准差、总和,进行简单基准测试时发现,10 万个数字进行计算时,大概需要 70ms,20 个指标同时计算就需要 70 * 20 = 1400 ms,再多数据和指标就会继续上升,也就是说极限情况计算理论上可以达到 4 秒以上,不太友好

于是,正好最近在学习 tauri 和 rust,就简单写一个 npm 包,使用 WebAssembly 来运行计算功能,计算代码也不复杂就不展示了,测试下来每个指标 10万数据需要 20 ms 左右,有波动,但基本上稳定在 js 计算的 1/4 时间消耗

但是!写完之后发现,更麻烦的是该怎么在项目中接入这些包,项目比较老,用的还是 webpack4,于是就调查总结了一下,在不同构建工具中使用 wasm

wasm-pack

  • wasm-bindgenrust/js底层互操作库和 cli 工具,实现 rust/js 类型转换,生成绑定代码
  • wasm-pack:基于 wasm-bindgen 的高级构建工具链,集成了 wasm-opt 等优化文件大小的工具,自动化了构建、优化、打包发布到npm的完整流程
sh 复制代码
# 检查版本和安装 wasm-pack
cargo -V
rustup update standable
cargo install wasm-pack
cargo install --list

# 用 wasm-pack 创建项目
# 具体功能代码略过,现在只需要打通流程,使用 demo 自带代码即可
wasm-pack new wasm-tools

# 打包成不同版本包
wasm-pack build --scope huli66 --target bundler
wasm-pack build --scope huli66 --target web

# 发布到 npm,前置条件是 npm login,手动使用 npm publish 也行
wasm-pack publish

--scope huli66 使用自己的 npm 用户名作为域,生成的 pkg 下面的 package.jsonname 也会带上 @huli66 前缀

两种打包 target 的区别

特性 bundler web
构建目标 --target bundler --target web
加载方式 同步/内联 异步/fetch
需要 init() 不需要 需要
需要 MIME 配置 不需要 需要
构建工具支持 需要 不需要

bundler

优点 内联到代码中,不需要配置 MIME,新版本打包工具支持都比较成熟

如果作为工具包使用,体积不大,推荐 bundler 方式,发布到 npm,前端使用一般加个 loader 或者 plugin 比较方便,不一定有权限配置 nginx(卑微)

web

优点 异步加载,如果 wasm 文件体积较大,不会阻塞主线程,放在静态文件目录中,可以开启 gzip 压缩减小加载体积 不需要构建工具支持,如果是老项目使用 webpack3 这种,或者不想找版本合适的 loader plugin 等,可以使用这种方式,只需要在生产环境的 nginx 上配置 MIME 类型(新的 nginx 配置默认支持)

nginx 复制代码
# mime.types,推荐修改,所有后缀为 .wasm 的文件都会自动带上返回头 Content-Type: application/wasm
types {
	application/wasm           wasm;
}

# 或者 default.conf 手动指定某个目录下的文件都带上指定返回头
location /static/wasm {
	add_header Content-Type application/custom;
}

可能遇到的问题:

直接调用 init() 出现报错 webpack4 不支持 import meta,可以在包中找到相关代码,删掉,或者尝试手动引入 .wasm 文件然后进行使用 console 出现乱码

js 复制代码
CompileError: WebAssembly.instantiate(): expected magic word 00 61 73 6d, found 3c 21 64 6f @+0
bash 复制代码
开发环境没有配置 `application/wasm`
vite 中配置
webpack5 配置
webpack4 配置

所有情况

打包工具 --target web --target bundler
vite 配置 MIME vite-plugin-wasm
webpack5 experiments: { asyncWebAssembly: true, syncWebAssembly: true }, experiments: { asyncWebAssembly: true, syncWebAssembly: true },
webpack4 配置 MIME 不推荐,loader 已废弃

可以使用 @huli66/test-wasm-web @huli66/test-wasm-bundler 两个包在自己的项目中尝试一下,代码如下

  • vite项目 使用 web 包需要开发环境和生产环境都配置 MIME,可以考虑把 wasm 文件放在静态服务器上,远程拉取进行 init bundler 包使用
js 复制代码
// vite.config.js
import wasm from 'vite-plugin-wasm';

export default defineConfig({
	plugins: [
		wasm()
	]
})
  • webpack5 项目 最简单,配置之后两种方式都能很简单运行
json 复制代码
{
	"experiments": {
		asyncWebAssembly: true,
		syncWebAssembly: true
	}
}

使用功能

js 复制代码
import {calculate_statistics as calc2} from '@huli66/test-wasm-bundler';
import init, {calculate_statistics} from '@huli66/test-wasm-web'

init().then(() => {
	const numbers = [1, 2, 3, 4, 5];
	const result = calculate_statistics(numbers);
	console.log(result, result.mean, result.median, result.standard_deviation);
});

const res2 = calc2([6, 7, 8, 9, 10]);
  • webpack4 项目 推荐使用 web 包,远程引入
相关推荐
网络点点滴5 分钟前
Vue3路由的props
前端·javascript·vue.js
last demo10 分钟前
grep和sed
linux·运维·前端·chrome
-曾牛12 分钟前
深入解析 XSS 漏洞:原理、分类与攻防实战
前端·安全·web安全·网络安全·渗透测试·xss·原理解析
JK凯17 分钟前
前端调试技巧
前端·visual studio code·前端工程化
开源之眼25 分钟前
github star 基础IO 文件在内核中是怎么被管理的 重定向的含义 在自定义shell中加入重定向
前端
JZXStudio25 分钟前
独立开发者亲测:MLX框架让我的App秒变AI原生!15年iOS老兵的2025新感悟
前端·ios
cindershade26 分钟前
Vue 3:我在真实项目中如何用事件委托
前端
我叫黑大帅26 分钟前
存储管理在开发中有哪些应用?
前端·后端·全栈
鲨叔26 分钟前
zustand 从原理到实践 - 原理篇(2)
前端·react.js
Heo29 分钟前
先把 Rollup 搞明白,再去学 Vite!
前端·javascript·面试