同步實例化

查看完整原始碼

此範例展示如何同步初始化 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://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
             * @see https://developer.mozilla.org/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({ module: 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" });

就是這樣!請務必閱讀部署選項,以了解在沒有打包工具的情況下部署意味著什麼。