JavaScript Mapping for Modules

On this page:

Default Mapping for Modules

The default mapping for a Slice module maps to a JavaScript object with the same name as the Slice module. The mapping preserves the nesting of the Slice definitions. For example:

Slice
module M1
{
    // Definitions for M1 here...
    module M2
    {
        // Definitions for M2 here...
    }
}

// ...

module M1    // Reopen M1
{
    // More definitions for M1 here...
}

This definition maps to the corresponding JavaScript definitions:

JavaScript
(function(module, require, exports)
{
    var Ice = ...
    var _ModuleRegistry = Ice._ModuleRegistry;
    var M1 = _ModuleRegistry.module("M1");
 
    // Definitions for M1 here...
 
    M1.M2 = _ModuleRegistry.module("M1.M2");
 
    // Definitions for M2 here...
 
    // More definitions for M1 here...

    exports.M1 = M1;
}(...));

The generated code exports the top-level modules. For browsers it adds symbols to the global window object and for NodeJS it uses the native exports object.

When developing for NodeJS, you include the various Ice components with require statements as shown below:

JavaScript
var Ice = require("ice").Ice;
var IceGrid = require("ice").IceGrid;
var IceStorm = require("ice").IceStorm;
...

Importing the generated code for your own Slice definitions works the same way:

JavaScript
var M1 = require("M1Defs").M1;

This example assumes the generated Slice definitions are in the file M1Defs.js.

In a browser application, the necessary JavaScript files are usually loaded via HTML script tags:

<script type="text/javascript" src="Ice.js"></script>
<script type="text/javascript" src="M1Defs.js"></script>
<script type="text/javascript">
    // You can now access Ice and M1 as global objects
</script>

The file Ice.js shown above only provides definitions for the Ice run time; you would need to explicitly include the corresponding files for any other Ice components that your application needs, such as IceGrid.js.

Alternate Mapping for Modules

Ice 3.7 introduces support for an alternative mapping for Slice modules. The alternate mapping differs from the standard mapping in the way that modules are imported and exported. With this new mapping the import and export are done using the standard JavaScript import and export statements.

Like with the default mapping, each Slice module maps to a JavaScript object with the same name, and only the top-level modules are exported. Using our previous example we need to add the [["js:es6-module"]] global metadata to enable the new module mapping:

Slice
[["js:es6-module"]]
module M1
{
    // Definitions for M1 here...
    module M2
    {
        // Definitions for M2 here...
    }
}

// ...

module M1    // Reopen M1
{
    // More definitions for M1 here...
}

This definition maps to the corresponding JavaScript definitions:

JavaScript
import { Ice } from "ice";
const _ModuleRegistry = Ice._ModuleRegistry;
//...
let M1 = _ModuleRegistry.module("M1");
//...
M1.M2 = _ModuleRegistry.module("M1.M2");
// ...
export { M1 };


Using ES6 modules in the browser

When using the es6 module mapping in a browser you will typically use it in conjuntion with a JavaScript module bundler like WebPack or Rollup. You will need to define a global "ice" object see sample configurations bellow:

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  externals: {
      "ice": "window"
  }
};

See https://webpack.js.org/configuration/externals/

// rollup.config.js
export default {
    input: 'main.js',
    output: {
        file: 'bundle.js',
        format: 'iife',
        globals: {
            ice: 'window'
        }
    },
    external: ['ice'],
};

See https://rollupjs.org/

See Also