Deploying on Node.js

When run from the IDE, the debugger takes care of putting all the pieces for your WebAssembly executable into place and launch them in the Node.js runtime. For actual deployment in your larger Node.js project, some additional thought is needed.

Essentially, there are at least three files generated by with a WebAssembly project:

  • RemObjectsElements.js – this file is shared by all Elements WebAssembly modules, and contains glue code for the interaction between JavaScript and WebAssembly. While it is generated next to the executable as part of the build, it is a static file and is not affected by the contents of your project. If you deploy more than one WebAssembly module to the same page, you only need one copy of this file.
  • MyModule.js – this file is generated during build and contains project-specific APIs to let JavaScript code interact with the specific types and APIs your module exposes.
  • MyModule.wasm – this, finally, is the actual executable containing the code you wrote, compiled to WASM.

Depending on your project type and contents, additional files might be generated or copied to the output folder, such as resources.

These are in addition to another "entry.js" JavaScript file contained in your project that defines the Node.js entry point that's mainly used for debugging purposes. For a real-life deployment, the APIs exposed by your WebAssembly module will more likely be accessed from existing JavaScript code that is already part of your larger Node.js project.

Using a WebAssembly Module from Your Existing Node.js Project

The default template includes the entry.js file mentioned above, which is there to ease debugging and deployment, but that's not a requirement. The compiler-emitted MyModule.js file can be used directly with Node.js' require() function:

var MyModule = require("./MyModule").MyModule;

MyModuleis the output name of your project. This.jsfile exposes APIs to access all exported member of your WebAssembly project. There is also a matchingMyModule.d.ts` file to allow for use from TypeScript-based projects.

The base MyModule type exposes a single named instantiate(). instantiate() accepts both an URL string or a ByteArray type to load the .wasm file. For Node.js projects, the ByteArray version should be used, for example by loading it with fs.readFileSync():

const fs = require('fs');
const path = require('path');
var MyModule = require("./MyModule").MyModule;
MyModule.instantiate(fs.readFileSync(path.resolve(__dirname, './MyModule.wasm'))).then(function(result) {
    ...
});

The Promise-typed return of instantiate() will have the resulting WebAssembly module as parameter. This will expose members for the APIs exposed by your WebAssembly module, as static methods (e.g. result.RemObjects_Elements_System_Math_Sin (for RemObjects.Elements.System.Math.Sin) and exported types (e.g. result.Program in the default template, which can be called to instantiate then and call instance members on).

const fs = require('fs');
var MyModule = require("./MyModule").MyModule;
MyModule.instantiate(fs.readFileSync(path.resolve(__dirname, './MyModule.wasm'))).then(function(result) {

    // most roundabout way to call sin:
    console.log("Sin call: " + result.RemObjects_Elements_System_Math_Sin(3)); 

    // instantiate Program
    var prog = result.Program();

    // call the HelloWorld instance method on it:
    prog.HelloWorld();
});

Note that the MyModule.js file depends on RemObjectsElements.js.

See Also