同步实例化

查看完整源代码

此示例展示了如何同步初始化 WebAssembly 模块,而不是 异步 初始化。在大多数情况下,默认的异步初始化模块的方式就足够了。但是,在某些情况下,您可能希望按需延迟加载模块,并同步编译和实例化它。请注意,这仅在主线程之外有效,并且由于大型模块的编译和实例化可能很昂贵,因此您应该仅在您的用例中绝对需要时才使用此方法。否则,您应该使用 默认方法

对于这种部署策略,不需要 Webpack 等打包器。有关部署的更多信息,请参阅 专用文档

首先,让我们看一下我们的小型库


# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(value: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    log(&format!("Hello, {}!", name));
}

#}

接下来,让我们看一下 `index.html`

<!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>
    <script>
      /**
       * First off we spawn a Web Worker. That's where our lib will be used. Note that
       * we set the `type` to `module` to enable support for ES modules.
       */
      const worker = new Worker("/worker.js", { type: "module" });

      /**
       * Here we listen for messages from the worker.
       */
      worker.onmessage = ({ data }) => {
        const { type } = data;

        switch (type) {
          case "FETCH_WASM": {
            /**
             * The worker wants to fetch the bytes for the module and for that we can use the `fetch` API.
             * Then we convert the response into an `ArrayBuffer` and transfer the bytes back to the worker.
             *
             * @see https://mdn.org.cn/en-US/docs/Web/API/Fetch_API
             * @see https://mdn.org.cn/en-US/docs/Glossary/Transferable_objects
             */
            fetch("/pkg/synchronous_instantiation_bg.wasm")
              .then((response) => response.arrayBuffer())
              .then((bytes) => {
                worker.postMessage(bytes, [bytes]);
              });
            break;
          }
          default: {
            break;
          }
        }
      };
    </script>
  </body>
</html>

否则,其余的魔法发生在 `worker.js` 中

import * as wasm from "./pkg/synchronous_instantiation.js";

self.onmessage = ({ data: bytes }) => {
  /**
   * When we receive the bytes as an `ArrayBuffer` we can use that to
   * synchronously initialize the module as opposed to asynchronously
   * via the default export. The synchronous method internally uses
   * `new WebAssembly.Module()` and `new WebAssembly.Instance()`.
   */
  wasm.initSync(bytes);

  /**
   * Once initialized we can call our exported `greet()` functions.
   */
  wasm.greet("Dominic");
};

/**
 * Once the Web Worker was spawned we ask the main thread to fetch the bytes
 * for the WebAssembly module. Once fetched it will send the bytes back via
 * a `postMessage` (see above).
 */
self.postMessage({ type: "FETCH_WASM" });

就是这样!请务必阅读有关 部署选项 的内容,以了解在没有打包器的情况下部署的含义。