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 包,远程引入
相关推荐
子兮曰16 小时前
OpenClaw入门:从零开始搭建你的私有化AI助手
前端·架构·github
吴仰晖17 小时前
使用github copliot chat的源码学习之Chromium Compositor
前端
1024小神17 小时前
github发布pages的几种状态记录
前端
不像程序员的程序媛19 小时前
Nginx日志切分
服务器·前端·nginx
北原_春希19 小时前
如何在Vue3项目中引入并使用Echarts图表
前端·javascript·echarts
尽意啊19 小时前
echarts树图动态添加子节点
前端·javascript·echarts
吃面必吃蒜19 小时前
echarts 极坐标柱状图 如何定义柱子颜色
前端·javascript·echarts
O_oStayPositive19 小时前
Vue3使用ECharts
前端·javascript·echarts
竹秋…19 小时前
echarts自定义tooltip中的内容
前端·javascript·echarts
宝贝露.19 小时前
Axure引入Echarts图无法正常显示问题
前端·javascript·echarts