Configuration
You should require only one script tag on your html since Arenite can take care of loading your javascript. This is advisable as there is a mechanism within Arenite to run in different flavors with different files
(ex: dev with all source files and prod with minified versions)
There are three ways to configure your instances to be registered with Arenite. You can use object configuration, annotation-based configuration or an AMD-style call to define
. You can use all at the same time if such is desired.
A base object is always required for at the very least declaring the dependencies.
For the dev API documentation please go here.
Object Configuration
The object configuration relies on a simple object to define the desired properties for arenite to act upon.
Expose
The property expose is name of the variable to be used for exposing the arenite instance in the window object. This property can also be a function to determine if the variable should be exposed.
Expose Arenite as a window variable arenite
:
Arenite({
expose: 'arenite',
...
});
Expose Arenite as a window variable arenite
only if a mode has been specified:
Arenite({
expose: function(arenite){
if (arenite.url.getUrl().mode){
return 'arenite'
}
},
...
});
Imports
For any non-trivial web-application you can (and should) separate your configuration into several different
components/files, known to arenite as modules
. These can then be specified in your main configuration (usually in index.html).
Arenite({
imports: {
"templates": {
"module": "doT",
"vendor": "arenite/template-extension",
"version": "1.0.2"
...
}
});
The key used in imports is used to uniquely identify each imported modules.
module
is the name/path of the module.
If no vendor is defined, it will use the name as a relative path. If the vendor is defined it will import the module from the repository (defaults to //cdn.rawgit.com/{vendor}/{version}/{module}/
and can be overriden by defining the config property repo
)
This name must correspond to the relative path of the configuration for the module.
vendor
optional specifies the vendor of the module you are about to import.
version
optional Defines which version of the module to fetch.
Note 1: Any arenite and non-arenite properties defined are merged and exposed in the property config
of arenite.
Note 2: Local modules are packaged into the minified files by the gulp plugin while non-local are not.
Note 3 Any module must have a module.json
file with the configuration for that module.
Context
The context
is composed of four sections, all of them optional.
Dependencies
A minimal initial object based configuration is required to at the very least specify the resources. The dependencies
section of the context is the configuration part where you define the script to load.
Note there is a default
entry in this element and that will be the files loaded by default.
You can add any other sections you’d like and trigger those alternatives by appending the query param mode
to the url.
Arenite({
context: {
dependencies: {
default: {
sync: [
...
],
async: [
...
]
}
}
}
});
Example: ...index.html?mode=debug
will attempt to load scripts defined in a debug
section.
Each dependency configuration contains two lists,sync
and async
which are used to list your scripts that need to be loaded synchronously or can be loaded asynchronously respectively.
Note that all sync
scripts are loaded one after the other and only then the async
scripst are loaded in parallel.
The entries can be simple strings with the location of the script:
Arenite({
context: {
dependencies: {
...
dev: {
sync: [
'//code.jquery.com/jquery-2.1.3.min.js'
]
...
}
}
}
});
Or you can, besides specifying the script, define the dependency extracts a variables from the window and registers them in arenite as an instances:
Arenite({
context: {
dependencies: {
...
dev: {
sync: [
{
url:'//code.jquery.com/jquery-2.1.3.min.js'
instances:{
'jquery':'$'
...
},
init:function(arenite){...}
}
...
]
}
}
}
});
url
URL from which to retrieve the script.
instances
Object with the list of variables to extract from window and register in arenite’s context (the key is the instance name and the value is the variable name in the window object)
init
is an optional function that is executed after the script is imported and before the instance is extracted from the window object.
Instances
This section declares the instances that are to be wired and registered in the arenite context.
Any instance declared in this section can be accessed using arenite.context.get('model')
where ‘model’ is the name of the instance to retrieve.
An instance is composed of four elements: namespace
, args
, init
and the optional factory
flag.
The namespace
is a string declaring the function to execute to create the instance.
args
is the list of arguments to be passed when executing the namespace
function and init
is the function to initialize the instance (). The flag factory
, which is false by default, defines if a new instance should be returned everytime the dependency is requested.
instances: {
...
todo: {
factory: true,
namespace: 'App.Todo',
args: [
{ref: 'arenite'},
{ref: 'model'},
{
instance: {
namespace: 'App.TodoView',
args: [
{ref: 'arenite'},
{ref: 'jquery'}
]
}
}
]
}
...
}
There are four types of args
: ref
which declares the dependency is a arenite registered instance with the specified name, value
which is a raw value (string, number, array, object, etc…), instance
which is a declaration of an anonymous instance and exec
which is the declaration of an execution (see the Start section of this document for more details).
Anonoymous instances are used in the wiring and inherit the factory flag from its parent but are not registered in the context. The anonymous instances are particularly useful if you use MVC or MVP design patterns where only the controller/presenter are registered in the context and the view can be declared (instantiated) for it but are not accessible from other controllers/presenters since they don’t exist in the context.
Extensions
You register your extensions in this section. There are a few extensions defined in the arenite project itself like the event bus, a simple router, a local storage extension (using StorageJS), a templating extension (using doT) and a test runner for jasmine with blanket code coverage.
An extension is pretty much a regular instance that instead of being added to the context registry is used to extend the arenite object itself.
...
extensions: {
templates: {
namespace: 'Arenite.Templates',
args: [
{ref: 'arenite'},
{ref: 'doT'}
],
init: {
wait: true,
func: 'add',
args: [
{value: ['build/templates.html']}
]
}
}
bus: {
namespace: 'Arenite.Bus'
}
}
...
The name of the instance is used as the collection of utility functions. The sample snippet will add the return structure from Arenite.Bus into arenite.bus and Arenite.Templates into arentite.templates.
Having wait: true
in an extension declaration will cause arenite to hold off the processing of the instances
section until the extension has been completely instantiated and resolved. The callback to mark the instance as ready is passed as the last argument of the init function of the instance.
Start
The start
section as the name implies is used to start the application after everything has been wired and initialized. It is a collection of function executions that is ran sequencially.
...
start: [
{
instance: 'model',
func: 'load'
}
],
...
The structure of the function executions is instance
declaring the instance to use (the name), func
the name of the function to be used and args
the list of arguments. Starts can also be declared by using func
as an actual Function that receives the arguments declared in the args
.
...
start: [
{
func: function (model) {
model.load();
},
args:[
{ref:'model'}
]
}
]
...
Full example
Here’s a full configuration as used in Arenite’s TodoMVC demo app. For the complete source go here
{
"imports": {
"templates": {
"vendor": "arenite/template-extension",
"module": "doT",
"version": "1.0.2"
},
"storage": {
"vendor": "arenite/storage-module",
"module": "storagejs",
"version": "1.0.2"
},
"router": {
"vendor": "arenite/router-extension",
"module": "",
"version": "1.0.5"
}
},
"context": {
"dependencies": {
"default": {
"async": [
{
"url": "build/todo.min.js",
"instances": {
"jquery": "$"
}
}
]
},
"dev": {
"async": [
"//code.jquery.com/jquery-2.1.3.min.js",
"js/model.js",
"js/list/list.js",
"js/list/listView.js",
"js/list/toolbarView.js",
"js/todo/todo.js",
"js/todo/todoView.js"
]
}
},
"start": [
{
"instance": "model",
"func": "load"
}
],
"extensions": {
"templates": {
"init": {
"wait": true,
"func": "add",
"args": [
{
"value": [
"build/template.html"
]
}
]
}
}
},
"instances": {
"model": {
"namespace": "App.Model",
"args": [
{
"ref": "arenite"
},
{
"ref": "storage"
}
]
},
"list": {
"namespace": "App.List",
"init": "init",
"args": [
{
"ref": "arenite"
},
{
"ref": "model"
},
{
"instance": {
"namespace": "App.ListView",
"args": [
{
"ref": "arenite"
},
{
"ref": "jquery"
}
],
"init": "init"
}
},
{
"instance": {
"namespace": "App.ToolbarView",
"args": [
{
"ref": "arenite"
},
{
"ref": "jquery"
}
],
"init": "init"
}
}
]
},
"todo": {
"factory": true,
"namespace": "App.Todo",
"args": [
{
"ref": "arenite"
},
{
"ref": "model"
},
{
"instance": {
"namespace": "App.TodoView",
"args": [
{
"ref": "arenite"
},
{
"ref": "jquery"
}
]
}
}
]
}
}
}
}