site/source/docs/compiling/Modularized-Output.rst
.. _Modularized-Output:
By default, emscripten outputs regular JS scripts which can be loaded on the Web
via a script tag, or on the command line using Node or other JS runtime.
In this default configuration the generated :ref:module variable (and indeed
all of the emscripten internal symbols) are added to the global scope. This
means that only one emscripten-built program can be loaded in a given scope
(since multiple modules would clobber each other's state).
The :ref:modularize setting (along with other related settings) can be used to
isolate the generated module within its own private scope and/or allow multiple
instances of the same module to be created.
This section covers the various modularization options available and how to use them.
The :ref:modularize setting has two primary functions. Firstly, it
puts all of the generated code inside its own scope so that the global namespace
is not polluted when the JS is loaded (for example, via script tag).
Secondly, it allows multiple instances of the module to be created.
The generated factory function is async and it returns a promise of an instance of the program. It can be called any number of times to create multiple separate and isolated instances of the same program.
By default, the factory function is called Module, but it can be given a
unique name via the -sEXPORT_NAME setting.
For example, a program built using -sMODULARIZE -sEXPORT_NAME=Foo can
be instantiated using:
::
var myFoo = await Foo({ /* optional params */ }); myFoo._nativeMethod();
or:
::
Foo({ /* optional params */ }).then((myFoo) => { myFoo._nativeMethod(); }
If node is included in the -sENVIRONMENT setting then the generated module
also acts as a CommonJS module under node.
Because there is no global Module object in this case any parameters to the
module creation are passed via the optional parameter to the factory function.
For example, if you wanted to use a custom print method you could write:
::
var myFoo = await Foo({ print: myPrint });
The :ref:EXPORT_ES6 setting can be used to instead output JavaScript in the
form of an ES module. (The ES module format did not exist at time when the
MODULARIZE setting was first created otherwise this would likely be the
default).
Using an output filename that ends in .mjs will automatically enable this
setting.
In this mode the module has a single default export which is the factory function for creating new instances of the module. For example:
::
import Foo from './emcc-output.js'; var myFoo = await Foo({ print: myPrint });
The name Foo here can be whatever you choose and will always be assigned to
the default export of the module.
Emscripten has experimental support for performing only the encapsulation part of modularization, and not the ability to create multiple instances. In this mode a module is created that exports a single instance of the program rather than a factory function.
This setting implicitly enables :ref:export_es6 and will not work when
:ref:export_es6 is explictly disabled.
In this mode the default export of the module is an initializer function which allows input parameters to be passed to the instance. Other elements normally found on the module object are instead exported directly. For example:
::
// Import the default init function and a named native method import init, { _nativeMethod } from './emcc-output.js'; await init({ print: myPrint }); _nativeMethod();
Some major features still do not work in this mode. Many of these we hope to fix in future releases. Current limitations include:
Internal usage (e.g. usage within EM_JS / JS library code) of the Module
global does not work. This is because symbols are exported directly using
ES6 module syntax rather than using the Module global.
The wasmExports internal global does not exist.
ccall/cwrap are not supported (depends on the Module global).
:ref:minimal_runtime is not supported.
The output of file_packager is not compatible so :ref:emcc-preload-file and
:ref:emcc-embed-file do not work.
Source phase imports_ is a JavaScript proposal that adds support for importing
Wasm modules via ES import statements. This allows Emscripten to elide some of
the auto-generated code for finding and fetching the Wasm binary.
See :ref:source_phase_imports.
This setting implicitly enables :ref:export_es6 and will not work when
:ref:export_es6 is explictly disabled.
Wasm ESM integration_ is a WebAssembly proposal that allows Wasm instances to
be imported directly as ES modules. This allows Emscripten to elide a lot of
boilerplate code for linking up Wasm and JavaScript.
See :ref:wasm_esm_integration.
This setting implicitly enables :ref:export_es6 and sets :ref:MODULARIZE to
instance. Because of this all the same limitations mentioned above for
-sMODULARIZE=instance apply.
Some additional limitations are:
:ref:wasm_workers is not yet supported.
:ref:abort_on_wasm_exceptions is not supported (requires wrapping wasm
exports).
:ref:asyncify is not supported (depends on wasmExports global)
Setting :ref:wasm to 0 is not supported.
Setting :ref:wasm_async_compilation to 0 is not supported.
.. _Source phase imports: https://github.com/tc39/proposal-source-phase-imports .. _Wasm ESM integration: https://github.com/WebAssembly/esm-integration