Skip to content

Wrapping

lptr edited this page Sep 12, 2014 · 13 revisions

When you look at a Spaghetti module's JavaScript code, especially when it's already packaged into an application, it can look rather convoluted. This page explains the purpose of the multiple layers of wrapping around the compiled JavaScript code, and how they work. Check the workflow page on how the steps follow each other.

The "Raw" JavaScript

When your Haxe or TypeScript code is compiled, the resulting JavaScript code resembles a part of a function, but without the actual function:

// lots of JavaScript stuff
var module = ...;
// lots more of JavaScript stuff
return module;

Bundling

The module bundle's purpose is to put everything required to use your module in a single ZIP file. The JavaScript code inside the bundle is wrapped in a function call that looks like this:

module(function(Spaghetti) {
    // lots of JavaScript stuff
    var module = ...;
    // lots more of JavaScript stuff
    return module;
})

Packaging

Packaging is the operation that makes an executable JavaScript application out of your modules.

The Spaghetti Object

The Spaghetti parameter of the anonymous function passed to the bundles JavaScript is the way for the module code to interact with the outside world. It contains metadata about the module (name, version), the Spaghetti version used to build it, references to dependent modules, and some utility functions to access resources. You can access the metadata and the resource-handling functions via a Spaghetti class (in the root namespace) both in Haxe and TypeScript. You should not need to access dependent module information from this object, as Spaghetti will generate proxy classes in your chose language to access other modules.

{
    getSpaghettiVersion: function() {
        return "2.0";
    },
    getName: function(){
        return "com.example.test";
    },
    getVersion: function() {
        return "1.0";
    },
    getResourceUrl: function(resource) {
        if (resource.substr(0, 1) != "/") {
            resource = "/" + resource;
        }
        return baseUrl + resource;
    },
    "dependencies": {
        // ...
    }
}

Module Data Object

Spaghetti wraps your module's returned object into a module data object that also contains the module version, and the Spaghetti version used to generate it:

{
    "module": module(function (Spaghetti) {
        // lots of JavaScript stuff
        var module = ...;
        // lots more of JavaScript stuff
        return module;
    }),
    "version": "1.0",
    "spaghettiVersion": "2.0"
}

Loader Wrapping and Dependencies

In order to keep Spaghetti small, we rely on existing tools to load modules in an application. As there is no standard JavaScript module format yet, we have to support both AMD and CommonJS modules. Spaghetti modules need to be wrapped to be used by either of these systems.

For AMD the module gets wrapped into something like this:

define(["require", "com.example.alma", "com.example.bela"], function() {
    var dependencies = arguments;
    var Spaghetti = {
        "modules": {
            "com.example.alma":dependencies[1],
            "com.example.bela":dependencies[2]
        },
        // ...
    };
    // ...
    return {
        "module": module(function (Spaghetti) {
            // lots of JavaScript stuff
            var module = ...;
            // lots more of JavaScript stuff
            return module;
        }),
        "version": "1.0",
        "spaghettiVersion": "2.0"
    };
});

For CommonJS it looks something similar to this:

var Spaghetti = {
    "modules": {
        "com.example.alma":require("com.example.alma"),
        "com.example.bela":require("com.example.bela")
    },
    // ...
};
// ...
module.exports = {
    "module": module(function (Spaghetti) {
        // lots of JavaScript stuff
        var module = ...;
        // lots more of JavaScript stuff
        return module;
    }),
    "version": "1.0",
    "spaghettiVersion": "2.0"
};

Analytics

Clone this wiki locally