前面我们也简单的接触过WebAssembly
:rust基础学习--搭配webAssembly - 知乎 (zhihu.com),也曾将我们之前写的扫雷小游戏编译成wasm
部署到web上:rust基础学习--基于Bevy实现扫雷小游戏day8 - 知乎 (zhihu.com)。
但是我们实际上都只是在学如何套壳子,没有任何涉及逻辑的,所以想了下准备来写一个babel
插件。
虽然有些本末倒置,毕竟要写感觉可以直接基于swc
去写。
但是别忘了,旧项目是属于能不动基本就不动的,所以要把旧项目的babel
替换成swc
,需要技术审核比如插件支持度什么的,所以对于旧项目来说,成本最低最稳定的还是使用babel
。
另外说下这里不分析性能、不追求代码优雅,只是一个方案,github链接:
因为这个插件的目的是在项目编译阶段,所以自然是node
环境,到时打包wasm
的target
也得是nodejs
。
其实一两年前公司的一个项目重构,在重构过程中因为大量的无注释代码搞得头疼,就有了强制开发写函数注释的想法。
那么我们需要整理下:
.js
文件export
出去的function
(包括箭头函数)第一点知道是什么文件这点简单,有的是办法,但是第二点和第三点就比较麻烦了,我们需要知道代码长什么样。
这种时候自然是我们的babel
上场,有了它,我们可以轻松知道哪些是export
的:exportdeclaration
然后我们在这个基础上去分析第三点即可。
于是我基于这个想法实现了一个babel
插件,代码比较简单,这里直接放出:
ExportDeclaration
:使用了export
关键字的leadingComments
:放在函数头部的就是leadingComments
FunctionDeclaration
:函数声明,比如export function xx () {}
VariableDeclaration
:变量声明,比如export const xx = xxx
,因为箭头函数和函数也可以这么声明,所以我们还需要在里面判断,ArrowFunctionExpression
和FunctionExpression
这两种。其它不多说了,相信大家对babel
或多或少有所了解,如果有哪里不懂可以评论区里说下。
后面我们rust
就不解释了~
我们这里直接创建lib
的:
然后配置下Cargo.toml
:
噢,差点忘了,在这之前你还需要安装wasm-pack
,至于如何安装,可以去看搭配WebAssembly
那篇文章,这里不多说。
这就行了
这里直接贴代码:
#[wasm_bindgen]
,如果你的函数需要暴露到js
中,那么这个是必须的。wasm_bindgen::closure::Closure::wrap
:将一个闭包转换成js
函数,其实js-sys
提供了Function
,并且可以基于它创建js
函数,但是这就本末倒置了,我们希望的是逻辑是rust
实现的。这里也不一定要用函数,也可以是一个闭包。Reflect::set
和Reflect::get
不用多说,给一个对象赋值和读对象的键值,这里我是通过递归去寻找深层的字段,如果你有更好的方案请务必在评论区里说下,不胜感激~declarations.map
:也就是Array::map
,注意不要用iter().map()
,这样是会报错的,打了半天log
才发现。代码写的有些乱,因为遇到一些类型转换之类的问题,它会很暴力的直接panic
,并且错误信息不可读,所以这里无奈写了一堆错误log
和兜底赋值,不然一个?
就解决了。
其它也没啥好说的了,逻辑也就这样。
然后我们来打包。
这里我们直接通过npm
来运行指令,基于npm
的原因是后面如果我们想打包成一个npm
包,那么npm
是必要的,所以直接省事:
然后配置下script
:
out-dir
:表示打包的文件夹名字--out-name
:入口文件名-t
:自然就是target
,这里我们选择nodejs
然后打包完成,在根目录会出现一个dist
文件夹:
那么到这就完成了
因为我们没有发布npm
包,所以只能手动将这个文件夹里的内容复制到项目中,inedx.js
中有对wasm
的加载逻辑,所以我们不必写load wasm
的逻辑,直接导入即可:
就不测试了,主要是得放图,很麻烦~
内容很少,但是耗时很长,因为还在学习中没有好的调试方案。。。如果你有好的调试方案请务必和我说下,谢谢!