介绍一个WebAssembly的小玩具

82307616 2019-06-26

名词解释区域

WebAssembly是一种新的字节码格式。它的缩写是".wasm", .wasm 为文件名后缀,是一种新的底层安全的二进制语法。。它被定义为“精简、加载时间短的格式和执行模型”,并且被设计为Web 多编程语言目标文件格式。 这意味着浏览器端的性能会得到极大提升,它也使得我们能够实现一个底层构建模块的集合,例如,强类型和块级作用域。

TypeScript是JavaScript类型的超集,它可以编译成纯JavaScript。

AssemblyScript 是AssemblyScript组织的一个开源项目,该项目将严格类型的TypeScript通过Binaryen编译为WebAssembly,并且他是一个NodeJs项目,这使我们前端开发人员写WebAssembly成为可能。


关于WebAssembly

首先WebAssembly现在还处于发展阶段,从https://caniuse.com/#search=W... 看浏览器支持程度较为一般,另外目前在整个业界还处于尝试阶段,参考WebAssembly在白鹭引擎5.0中的实践,但是作为新技术我们还是需要及时跟进掌握了解。

介绍一个WebAssembly的小玩具

AssemblyScript

AssemblyScript的出现并不意外,可以说终于等到了这个开源项目的诞生,TypeScript是强类型语言,利用TypeScript去编译WebAssembly最为合适,一直以来都坚信这一点终于变成的现实。

首先想学习AssemblyScript写法的同学,请参考 https://github.com/AssemblySc...,本文不在过多说明。注意文档里面介绍的一些类型限制,一些类型定义。

重点是下面向大家介绍一下AssemblyScript的Webpack loader,教大家如何在Webpack中使用AssemblyScript:assemblyscript-typescript-loader

assemblyscript-typescript-loader

Loader for webpack to compile typescript with AssemblyScript and bundle it to wasm or btyes string。

assemblyscript-typescript-loader可以将AssemblyScript代码编译为在浏览器端运行的wasm文件,主要处理了如下几种情况:

  1. 将大于limit大小的AssemblyScript打包为wasm文件。
  2. 将小于limit大小的AssemblyScript直接作为二进制字符串打包到bundle。
  3. 提供WebAssembly Promise对象的回调。
  4. 对于不支持WebAssembly的浏览器做运行时兼容。

安装

npm i assemblyscript-typescript-loader --save

使用

webpack.config.js

module.exports = {
      module: {
        rules: [
          {
                test: /\.ts?$/,
                loader: 'assemblyscript-typescript-loader',
                include:/assemblyscript/,//to avoid a conflict with other ts file who use 'ts-load',so you can division them with prop 'include'
                options: {
                    limit: 1000,
                    name: `static/assembly/[name].[hash:8].wasm`
                }
            }
        ]
      }
    }

注意目前AssemblyScript只能支持将ts后缀的文件进行编译,但是在工程中可能和其他的ts文件(非AssemblyScript文件)产生loader冲突,所以请利用“include”和“exclued”属性对AssemblyScript和原生ts代码进行区分,参考上面示例。
更多的loader配置请参考官方文档:https://github.com/SinaMFE/as...

assemblyscript/moduleEntry.ts
注意该文件夹(assemblyscript)专门用于存放assemblyscript代码入口,防止和项目中其他typescript代码冲突。

var w: u32, // width
    h: u32, // height
    s: u32; // total size

/** Initializes width and height. */
export function init(w_: u32, h_: u32): void {
  w = w_;
  h = h_;
  s = w * h;
}

/** Performs one step. */
export function step(): void {
  var hm1 = h - 1,
      wm1 = w - 1;
  for (var y: u32 = 0; y < h; ++y) {
    var ym1 = select<u32>(hm1, y - 1, y == 0),
        yp1 = select<u32>(0, y + 1, y == hm1);
    for (var x: u32 = 0; x < w; ++x) {
      var xm1 = select<u32>(wm1, x - 1, x == 0),
          xp1 = select<u32>(0, x + 1, x == wm1);
      var n = (
        load<u8>(ym1 * w + xm1) + load<u8>(ym1 * w + x) + load<u8>(ym1 * w + xp1) +
        load<u8>(y   * w + xm1)                         + load<u8>(y   * w + xp1) +
        load<u8>(yp1 * w + xm1) + load<u8>(yp1 * w + x) + load<u8>(yp1 * w + xp1)
      );
      if (load<u8>(y * w + x)) {
        if (n < 2 || n > 3)
          store<u8>(s + y * w + x, 0);
      } else if (n == 3)
        store<u8>(s + y * w + x, 1);
    }
  }
}

index.js

import asmPromise from "./assemblyscript/moduleEntry.ts";
asmPromise.then(function(asmModule){
  // here you can use the wasm.exports
  asmModule.step();
})

在业务代码中引入assemblyscript入口文件,并返回Promise对象,在then中就可以使用到WebAssembly标准的输出。欢迎大家在项目中尝试哈,如果有问题请在github提issues,多谢。

另外附一些参考资料:

WebAssembly官网(http://webassembly.org/
WebAssembly on MDN(https://developer.mozilla.org...
AssemblyScript Wiki (https://github.com/AssemblySc...
assemblyscript-typescript-loader github (https://github.com/SinaMFE/as...

相关推荐