Vue项目中导入Wasm学习记录
Vue项目中导入Wasm学习记录
Vue项目中导入Wasm学习记录
webassembly官网如下
下面是官网对wasm的说明:
WebAssembly(缩写为Wasm)是基于堆栈的虚拟机的二进制指令格式。Wasm被设计为编程语言的可移植编译目标,支持在Web上部署客户端和服务器应用程序。
- Wasm堆栈计算机设计为以大小和加载时间高效的二进制格式进行编码。WebAssembly旨在通过利用各种平台上可用的通用硬件功能,以本机速度执行。
- WebAssembly被设计为以文本格式精美打印,用于调试,测试,实验,优化,学习,教学和手动编写程序。在网络上查看 Wasm 模块的源代码时将使用文本格式。
- WebAssembly 描述了一个内存安全的沙盒执行环境,甚至可以在现有的 JavaScript 虚拟机中实现。当嵌入到 Web 中时,WebAssembly 将强制执行浏览器的同源和权限安全策略。
- WebAssembly 旨在维护 Web 的无版本、功能测试和向后兼容的性质。WebAssembly 模块将能够调用进出 JavaScript 上下文,并通过可从 JavaScript 访问的相同 Web API 访问浏览器功能。WebAssembly 还支持非 Web 嵌入。
构建wasm项目
使用AssemblyScript构建wasm项目指南:Getting started | The AssemblyScript Book
以下是直接从这个网站中复制下来的
首先建立一个空文件夹,然后使用VsCode打开它,新建终端分别执行如下的命令,这里能执行node.js相关的命令,前提是安装node.js的时候记得配置系统环境变量
确保节点的最新版本.js (打开新窗口)并安装了它的包管理器 npm(随 Node.js 一起安装,然后切换到新目录并像往常一样初始化一个新的 Node.js 模块:
npm init
安装 AssemblyScript 编译器。让我们假设它在生产中不是必需的,并使其成为开发依赖项:
npm install --save-dev assemblyscript
安装后,编译器提供了一个方便的脚手架实用程序来快速设置新项目,位于当前目录中:而且这里注意的是,命令行中有一个英文字母的点,记得一定要写上
npx asinit .
运行命令成功之后,我们可以发现如下的目录
打开对应的目录文件,如下图所示,我们也可以自己写一个方法。
Concepts | The AssemblyScript Book这里有关于这个语言的语法格式要求
使用模块
中的示例现在可以通过调用 build 命令编译为 WebAssembly:assembly/index.ts
npm run asbuild
这样做会将编译的二进制文件、绑定和定义文件发出到目录中。build/
生成的测试用例可以使用以下命令执行:tests/index.js
,测试已下是否通过
npm test
构建后,该目录将包含像任何其他现代节点一样使用该模块的所有位.js 环境无害管理模块:
import * as myModule from "myModule";
生成的模块显示了如何在 Web 上使用模块。提供 Web 服务器的服务 模块目录(默认为 display )可以通过以下方式启动:index.html``index.html
index.html的代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<!-- <script type="module">
import { add, pringInt } from "./build/release.js";
// document.body.innerText = add(1, 2);
</script> -->
</head>
<body>
<div id="add"></div>
<hr>
<div id="pringInt"></div>
<script type="module">
import { add, pringInt } from "./build/release.js";
let addResult = add(1,2)
document.getElementById("add").innerHTML = `调用assembly目录下的index.ts的add()函数
的结果为1+2 = :${addResult}`
let pringIntResult = pringInt(10000)
document.getElementById("pringInt").innerHTML = `调用assembly目录下的index.ts的
pringInt()函数的打印结果 :${pringIntResult}`
</script>
</body>
</html>
npm start
请注意,根据用例的不同,并非所有文件都是必需的,并且它是安全的 以删除不需要的内容。如果出现任何问题,可以再次执行,这 将恢复已删除的默认文件,同时保留已编辑的文件。asinit
按住Ctrl+鼠标点击就可以跳到对应的网站了,或者复制网址到浏览器地址栏回车访问
在html中调用wasm的方法
在javascript使用wasm需要使用 WebAssembly JavaScript API实现,官网地址如下所示
使用 WebAssembly JavaScript API - WebAssembly |多核 (mozilla.org)
1、首先复制上面构建的release.wasm到对应的web项目中,release.wasm.map有没有都行,但是release.wasm要有
但是这里当我们运行的时候,f12就会发现报如下错误
Uncaught (in promise) TypeError: WebAssembly.instantiate(): Imports argument must be present and must be an object
这里有一个解决办法就是去我们构建wasm的项目那里,把自己写的方法的console.log注释掉,然后再重新
npm run asbuild
将得到的wasm复制到web项目中就可以了
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="loadwasm" style="background-color: pink;"></div>
<hr>
<div id="loadwasmprint" style="background-color: pink;"></div>
<script>
WebAssembly.instantiateStreaming(fetch("./release.wasm")).then(
(results) => {
// results?.instance?.exports这里面就有我们之前构建成wasm的两个函数add()、pringInt,具体看console.log(results.instance.exports)的结果
// console.log(results.instance.exports)
console.log(results?.instance?.exports)
var addResult = results.instance.exports.add(100,200)
document.getElementById("loadwasm").innerHTML = `加载了使用了wasm的add()方法,100+200=:${addResult}`
var pringIntResult = results.instance.exports.pringInt(2400)
document.getElementById("loadwasmprint").innerHTML = `加载了使用了wasm的pringInt()方法,调用结果如:${pringIntResult}`
})
async function wasm() {
// 这是另外一种读取文件的方式
const { instance: { exports } } = await WebAssembly.instantiateStreaming(fetch("./js/release.wasm"))
// 这个exports就有我们之前在构建wasm文件的的两个函数add()、pringInt()
console.log(exports)
}
</script>
</body>
</html>
结果如下所示,我们通过console.log(results?.instance?.exports)目前wasm中具有的函数方法
在Vue中调用wasm方法
在vue中读取wasm文件
wasm.js的代码如下
export var defaultExport = '这个是在vue中引入wasm的试验'
export async function getWasmExports() {
const { instance: { exports } } = await WebAssembly.instantiateStreaming(fetch("./js/release.wasm"))
// eslint-disable-next-line no-debugger
return exports
}
export var wasmExportsObj = {}
WebAssembly.instantiateStreaming(fetch("./js/release.wasm")).then(
(results) => {
// eslint-disable-next-line no-debugger
// wasmExportsObj = results.instance.exports
wasmExportsObj = results?.instance?.exports
})
export function test() {
return 66666
}
// 这种导出方式,在引入时不需要加{},而且只能有一个export default
// 如:import defaultExport, {wasmExportsObj, test, getWasmExports} from './utils/wasm'
export default defaultExport
APP.vu的代码如下所示
<template>
<div id="app">
<div>在这里调用了wasm中的add()方法</div>
<hr>
<el-input-number v-model="num1" label="描述文字"></el-input-number>
+
<el-input-number v-model="num2" label="描述文字"></el-input-number>
=
<span style="color:blue; font-size: 24px;">{{ sum }}</span>
<el-button type="primary" @click="sum3">计算</el-button>
<hr>
<el-input-number v-model="num3" label="描述文字"></el-input-number>
+
<el-input-number v-model="num4" label="描述文字"></el-input-number>
=
<span style="color:blue; font-size: 24px;">{{ sum2 }}</span>
<el-button type="primary" @click="sum3">计算</el-button>
<!-- <el-button type="primary" @click="sum4">计算</el-button> -->
</div>
</template>
<script>
import defaultExport, {wasmExportsObj, test, getWasmExports} from './utils/wasm'
export default {
name: 'APP',
data() {
return {
num1: 0,
num2: 0,
sum: 0,
num3: 100,
num4: 200,
sum2: 300
}
},
methods: {
async sum3() {
console.log(defaultExport)
var test2 = test()
console.log(test2)
// 加载调用加载wasm的方法
let getWasmExports2 = await getWasmExports()
console.log(`这个是wasm导出的接口对象,调用的是getWasmExports():`)
console.log(getWasmExports2)
console.log(getWasmExports2.add(1,2))
this.sum = getWasmExports2?.add(this.num1,this.num2)
console.log("=========================================================")
// 调用wasm的方法2
console.log(`这个是wasm导出的接口对象,调用的是wasmExportsObj`)
console.log(wasmExportsObj)
console.log(wasmExportsObj?.add(10000,30000))
this.sum2 = wasmExportsObj.add(this.num3,this.num4)
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 30px;
}
nav a {
font-weight: bold;
color: #2c3e50;
}
nav a.router-link-exact-active {
color: #42b983;
}
</style>
npm run serve后运行的结果如下所示
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)