App Runtime

The App Runtime, or sometimes just called apprt, is the core of any map.apps application. It is the App Runtime that reads an app configuration, loads the required bundles, creates component instances, and handles all the dynamic aspects of these bundles and components, that might come and go during the lifetime of an application.

Startup

This diagram demonstrates the startup flow of the App Runtime.

apprt launch

Following steps are performed during the framework start:

  1. The Launcher’s config locator resolves the app.json.

  2. The Launcher' bundle locator resolves the bundles.json file of the root of each bundle location specified in the app.json.

  3. The manifest.json files of required bundles are resolved, if not embedded in bundles.json, already.

  4. The Launcher creates the App Runtime.

  5. The Launcher installs and starts the system bundle in the App Runtime.

  6. The Launcher installs all other required bundles in the App Runtime.

  7. The Launcher starts the App Runtime. This starts all bundles, except for those that have the autoStartPolicy property set to "no".

After these steps the app is ready for use.

bundles.json

The bundles.json file is an index of bundles names (or rather paths) of bundles that available at the requested location. The index may map a bundle name to an empty object, or to an object with the content of the according manifest.json file inlined per available version.

Example of a bundles.json file mapping to an empty object
{
    "map-init": {},
    "toc": {}
}

If the value of a bundle name property is empty as in the example above, the bundle locator is resolving the content of the manifest.json file with a separate request.

For an example with inlined manifest.json content, see JS Registry service reference.

Launcher $apprt.startApp

The framework is started by the statement $apprt.startApp. To launch the framework following snippet can be used.

$apprt.startApp in index.html
<script type="text/javascript" src="<jsregistry-root>/apprt-core/<version>/boot.js"></script>
<script type="text/javascript">
  $apprt.startApp({
    param : "app",
    defaultApp : "traffic"
  });
</script>

When apprt-core/boot.js is loaded it makes the function $apprt.startApp globally available. This function provides two ways to start an application.

Use-case Sample Description

Start well-known app.

$apprt.startApp({
    app: "traffic",
    domId: "app-node"
});

App with name traffic is started.

The optional parameter domId defines the ID of a DOM node. The app is embedded inside this node.

Start app named by a query parameter.

$apprt.startApp({
  param : "app",
  defaultApp : "traffic"
});

Checks if a query parameter named app exists. If yes its value is interpreted as app name.

The function accepts the following options:

param: The name of the query parameter that contains the app name.

defaultApp: The name of the app that should be started if no query parameter is present.

domId: The ID of a DOM node where the app should be embedded.

Integrated app configuration

The parameter app supports a special configuration style - the so-called inline app definition - meaning that the content of an app.json file is declared directly inside the HTML page.

A definition looks like this:

inlined app.json
<script type="text/javascript" src="<registry-root>/apprt-core/<version>/boot.js"></script>
<script type="text/javascript">
$apprt.startApp({
    app: {
        "appName": "myapp",
        "load": {
            "allowedBundles": [
                "system",
                "templatelayout",
                "splashscreen",
                ...
            ]
        },
        "bundles" : {
            ...
        }
    }
});
</script>
<body class="start">
   ...
</body>

The JSON configuration of the app is directly embedded inside the app option of the $apprt.startApp.

These are special advanced features that should only be used when necessary.

There is a special "merge" mode. If you do not declare a load section in the app.json file within the HTML or you declare "load": { "merge": true} in the inlined app configuration, the appName is used to fetch a basic app configuration and the inline definition is merged into this base configuration to get the effective configuration. This allows to partially overwrite a common configuration.

The same behavior is supported if the query parameter app contains no name but an app.json file definition.

Config locator

When the Launcher starts an app, it internally uses a config locator to fetch the app configuration, that is, the app.json file. The configuration locator, for example, replaces the ${app} key used in the app.json files based on its configuration.

In the $apprt.startApp method you can specify following properties to customize the config locator:

Property Sample Description

configLocation

$apprt.startApp({
  configLocation: "apps"
})

The AMD prefix of the configuration location path. Use "builderapps" to locate app.json files of apps created in the map.apps Manager.

Required: No
Default: "apps"

configFilePattern

$apprt.startApp({
 configFilePattern: "{appName}/test.json"
})

A resolution pattern for the sub path in the configuration location. Can be used to map to a different file as the app.json file if required.

Required: No
Default: "{appName}/app.json"

Bundle locator

When an app starts the Launcher internally uses the bundle locator to fetch bundles.json files and manifest.json files from the bundle locations property configured in an app.json.

The following sections describe several ways to specify the bundle location.

AMD prefixes

To use an AMD prefix to identify a bundle location, you first need to register the package location at the AMD loader:

// assume that following package is registered at the AMD loader
require({
    packages: [{
        name: "myprefix",
        location: "http://localhost:8080/mybundles"
    }]
});

You can then use the prefix to define bundle locations like this:

Example "bundleLocations"
Value Effective location

"myprefix"

http://localhost:8080/mybundles/bundles.json

"myprefix/test"

http://localhost:8080/mybundles/test/bundles.json

"myprefix/mybundles.json"

http://localhost:8080/mybundles/mybundles.json

Concrete URLs

Use may also use concrete URLs to define a bundle location:

Example "bundleLocations"
Value Effective location

"http://localhost:8080/mybundles"

http://localhost:8080/mybundles/bundles.json

"http://localhost:8080/mybundles/mybundles.json"

http://localhost:8080/mybundles/mybundles.json

"./mybundles/mybundles.json"

Location relative to HTML page

Object syntax

In addition to the plain string syntax for bundle locations, you can also use a more flexible object syntax. The main reason to use the object syntax is to define additional properties which control the loading process from the registry.

To lookup myprefix and load mybundles.json, use:

{
    "load": {
        "bundleLocations":[{
            "name" : "myprefix/mybundles.json"
        }]
    }
}

To load bundles from http://localhost:8080/mybundles/bundles.json, use:

{
    "load": {
        "bundleLocations":[{
            // define a name and an explicit location
            "name" : "mybundles",
            "location" : "http://localhost:8080/mybundles"
        }]
    }
}

To lookup myprefix, load bundles.json, and control the bundle locator behavior specifying additional properties, use:

{
    "load" : {
        "bundleLocations":[{
            // define the location
            "name" : "mybundles",

            // list of bundle names which should not loaded from this registry.
            "excludes" : ["bundlename"],

            // jsonp not allowed for this registry
            "useJSONP" : false,

            // relative or absolute URL which should be requested to prefetch the JavaScript files from this registry
            "prefetch" : "./bundles.js",

            // disable the prefetching of JavaScript files for this registry
            "noprefetch" : true
        }]
    }
}

App-relative locations

To reference bundles stored inside an app folder, you can use the expression ${app}, and add sub-folders as required. ${app} will be resolved to the URL of the folder that the app.json was loaded from.

For example, setting the bundle location to "${app}/bundles"`will cause the bundle locator to search the `bundles.json file inside the bundles/ folder of the app.

JavaScript prefetching

This is a dynamic loading feature which ensures the JavaScript files needed by the app are fetched in a single request, which is much faster than single file fetching.

Only the preFetchBundles option of the Launcher enables the feature. It does not mean that it is enabled for all bundle locations.

JavaScript files are only prefetched from a BundleLocation if this is explicitly enabled for a bundle location.

It can be enabled in two different ways:

  1. use the object notation in the "bundleLocation" specification and define a prefetch property

  2. add a "__meta" property in a bundles.json

Enable pre-fetching
// in app.json (see also Configuration/BundleLocation section)
{
    "load" : {
        "bundleLocations" :[{
            name : "bundles",
            prefetch : "./bundles.js"
        }]
    }
}

// in bundles.json or registry response
{
    // registry/location meta information
    "__meta" : {
        "prefetch" : "./bundles.js"
    },

    "<bundle name>" : ...
    ...
}

// You can also use a non default "bundles.js" name, for example the JS Registry defines following:
__meta: {
    prefetch: "http://localhost:8080/resources/jsregistry/root/layer.js?requires=%7Binclude%7D&requires_skip=%7Bexclude%7D&locale=%7Blocale%7D"
}

// prefetch URL explanation:
// %7Binclude%7D is the string "{include}": placeholder for all required bundle names
// %7Bexclude%7D is the string "{exclude}": placeholder for all bundles to skip
// %7Blocale%7D is the string "{locale}"  : placeholder for the current locale