-
Notifications
You must be signed in to change notification settings - Fork 0
The Server side AMD Config file
The server-side AMD configuration is a JavaScript object that closely mirrors the client-side AMD configuration as detailed on the RequreJS web site and defines the paths and packages that relate AMD module identifiers to JavaScript and other resources, however, instead of specifying web resources, the server-side AMD config specifies URIs to resources on the server. The config file itself is specified as a resource URI. If the URI is not absolute (i.e. protocol specified), then the it is assumed to reside in the OSGi bundle that contains the plugin.xml defining the servlet. Server-side resources are specified using Universal Resource Identifiers (URIs) as specified by the java.net.URI class. The Aggregator provides support for URIs using the standard file protocol for files that reside on the server's file system, and the non-standard, Aggregator defined, namedbundleresource protocol for resources residing in OSGi bundles.
The URI to the server-side AMD config file is specified using the config servlet init-param in the <servlet> element defining the servlet.
The namedbundleresource protocol allows resources to be specified using the bundle symbolic name that the resource is contained in. A namedbundleresource URI looks similar to the following:
namedbundleresource://com.ibm.jaggr.sample.dojo/WebContent/dojo-release-1.8.0-src/dojo
which specifies the resource path dojo within the OSGi bundle with the symbolic name com.ibm.jaggr.sampled.dojo. URIs specified using the namedbundleresource protocol are not universal because multiple resources residing in different bundles using the same symbolic name may exist, and which resource the URI resolves to depends on the behavior of the OSGi class loader as it relates to resolving bundles. This ambiguity violates the rules governing URIs. It is, never the less, convenient to be able to specify resources that reside in named bundles using the URI syntax, so the Aggregator supports the use of the namedbundleresource protocol for URIs specified within the server-side AMD config file. The ambiguity around which bundle to use is dealt with by ensuring that the class loader of the application's bundle (the bundle containing the plugin.xml defining the servlet) is always used to load the bundle whose name is specified in the host part of the URI.
The Aggregator may be extended using the com.ibm.jaggr.service.resourcefactory extension point to support additional URI protocols, providing the ability to extend support to include resources residing within jar files, databases, etc. The default file and namedbundleresource protocols are supported using classes that implement this extension.
Strings of the form ${propertyName} may appear anywhere within the config JavaScript and will be replaced with the value of the named property. The value is obtained by calling BundleContext.getPropery() using the BundleContext of the contributing bundle, or if the named property is not defined there, then by calling any registered OSGi services that support the com.ibm.jaggr.service.IVariableResolver interface. Variable property substitution is performed before script evaluation. If a value cannot be found for a named property, then the string is left un-modified.
When the server-side config javascript is being evaluated, the following JavaScript variables are defined and in scope, and may be referenced by JavaScript expressions in your config:
- initParams
- An object of the name-value pairs defined in the servlet-init-params
- options
- An object of the name-value pairs defined in the Aggregator options
- headers
- An object of the name-value pairs specified in the bundle manifest for the contributing bundle (i.e. the bundle that instantiated the servlet)
- console
- An object containing logging methods such as error, warn, info and log. These methods can be used to write messages to the server logs from javascript code in the config
The baseUrl, paths and location properties specify resource URIs which may be either a string value, or a two element array of strings specifying primary and override URIs. The idea behind override URIs is to facilitate product customization by supporting a location on the file system where customized resources may be placed. Resources that exist in the override locations will be used instead of the corresponding resources in the location specified by the primary URI. In this scenario, the primary URI typically specifies an OSGi bundle, using the namedbundleresource URI scheme, while the override URI specifies a customization area on the server's file system.
Property Name | Description |
---|---|
baseUrl | The base URI to use for all relative URIs specified in this config. If baseUrl is not absolute, then it is assumed to be relative to the root of the bundle defining the servlet. Note that the property name specifies Url, with a lower-case L, instead of URI with an upper-case i, to maintain symmetry with the client-side config. This property may specify a single URI or primary and override URIs as described in Override URIs. Files and folders located under the folder specified by baseUrl are not scanned when the Aggregator builds the module dependency map used for require list expansion unless the depsIncludeBaseUrl property is specified with a value of true. |
paths | Path mappings for module names to resource URIs. The path URIs are assumed to be relative to baseUrl, unless the URI starts with a "/" or specfies a protocol. Path entries may specify a single URI or primary and override URIs as described in Override URIs. If a relative override is specified, then it is relative to the override URI of the baseUrl property if there is one, else it is relative to the primary URI of the base property. |
packages |
Defines the packages for the application. A package can be assocated with a module name/prefix. The package config can specify the following properties for a specific package:
|
aliases |
Specifies an array of vector pairs with alias mappings. Each array entry is a two element array with the first element specifying the string to replace, and the second element specify the replacement. Two forms of alias mappings are supported. The first form is a simple string substitution mapping with the first entry specifying the string to replace and the second specifying the string to replace it with. For example:
aliases: [ ["text", "dojo/text"] ] The second form allows for regular expression pattern mapping and the specification of the replacement as a string or as a function, For replacement functions, the has() function may be called to query the feature set specified in the request. Note that unlike the has() function on the client, this has() function returns either a boolean value, representing the value of the feature on the client after cooercing the value to a boolean type, or undefined if the feature was not specified in the request. aliases: [ [/^(.*)\/foo\/(.*)$/, "$1/bar/$2"] [/^(.*)\/backend\/(.*)$/, function($0,$1,$2){ return $1+(has("foo")?"/foo/":(has("bar")?"/bar/":"/backend/"))+$2; } ] ] Server-side aliases are provided in support of client-side aliases, which are supported by some AMD loaders including the Dojo loader. In general, server-side and client-side aliases should produce the same mappings. Because client-side aliases are resolved on the client before modules are requested, server-side aliases are not used to find requested modules. Instead, they are used in require list expansion, in order to correctly identify dependent modules so that their dependencies may be expanded within the require list of another module. An important significance of this detail is that if the mappings produced by an alias resolver are conditional upon the has.js feature set provided in the request, then the conditioned feature tests must be defined on the client for the request containing the require call that gets expanded to include the aliased module. This can occur well before the request for the aliased module itself. For this reason, server-side alias resolvers should always be implemented in such a way that alias resolution fails (and the module path is not changed) if the tests for the conditioned feature(s) are not yet defined. This will cause the aliased resource's dependencies to not be expanded in the require list (because it won't be found on the server) instead of potentially expanding the dependencies for the wrong module. Regular expressions specified in alias mappings are evaluated using Java regular expression classes for performance reasons, so you need to be aware of the subtle differences between java and javascript regular expressions. In addition to the JavaScript variables defined in Scoped variables above, the following variables are defined and in scope and may be referenced by your alias resolver function:
|
depsIncludeBaseUrl | Optional. If specified with a value of true, then the files and folders under the directory specified by baseUrl will be scanned when the Aggregator builds the module dependency map used for require list expansion. If false, then only the paths specified by the paths and packages properties are scanned. The default value is false. |
expires | Optional. Specifies the number of seconds in the future that cached responses in third-party caches should be validated by the server. Specifically, it specifies the value of the Cache-Control:max-age header that is returned with Aggregator responses. If this property is not specified, then no Cache-Control:max-age header is returned in the response. |
deps | Optional. This property is analogous to the client-side AMD config deps property, which specifies the modules that should be loaded before the application's require.callback method is called. On the server, this property is used to trim the list of expanded dependencies for all require list expansions. Any modules listed here, along with the nested dependencies of the listed modules, will be excluded from expanded require lists for all require() calls in the application. In general, the client-side and server-side AMD configs should both specify the same modules in the deps property, although, this is not a requirement. |
coerceUndefinedToFalse | If true, then the Aggregator will treat undefined features as if they were defined with a value of false. This applies to has.js feature trimming of javascript code. If this value is false, then has.js conditionals for undefined features are left unchanged. If the value is true, then conditionals involving undefined features are trimmed based on the value of the feature evaluating to false. The default value for this option is false. |
cacheBust | An arbitrary string specified by the application that is associated with the serialized meta-data for Aggregator caches and the module dependency maps. When these data structures are de-serialized on server restarts, the saved value is compared against the value that is read from the current config, and if the values don't match, then the de-serialized data is discarded and the caches and dependency maps are deleted and rebuilt. |
notice |
Specifies a URI to a resource containing arbitrary text that is included at the beginning of every Aggregator response. The notice text should be in the form of a JavaScript block comment. The Aggregator does not do any processing on the notice text.
If the URI is relative, it is assumed to be relative to the location of the config file. |
textPluginDelegators | Specifies an array of loader plugin module ids that delegate to the default text loader plugin. When performing dependency expansion of modules specified using the required URL query arg, required modules that specify plugins included in this list will be included in the response as if they were required by the text plugin. |
jsPluginDelegators | Specifies an array of loader plugin module ids that delegate to the AMD loader for javascript modules. An example of such a plugin is the i18n loader plugin (although this plugin is added automatically to jsPluginDelegators and so does not need to be explicitly specified in the config file). When performing dependency expansion of modules specified using the required URL query arg, required modules that specify plugins included in this list will be included in the response as if they were required by the default AMD loader for javascript modules. |
Aggregator extensions may support additional properties. For example, the CSS module builder supports config properties for controlling in-lining of image references and imported CSS. |
{ /* * Paths are relative the WebContent folder of the bundle containing this config. */ baseUrl: ['WebContent', '${MYAPP_CUSTOMIZATIONS}'], packages: [ { name: 'dojo', location: ['namedbundleresource://org.dojo-1.8.res/WebContent/dojo', 'dojo'], lib: '.' }, { name: 'dijit', location: ['namedbundleresource://org.dojo-1.8.res/WebContent/dijit', 'dijit'], lib: '.' }, { name: 'dojox', location: ['namedbundleresource://org.dojo-1.8.res/WebContent/dojox', 'dojox'], lib: '.' } ], paths: { "css": "js/css" // uses override path derived from baseUrl (i.e. ${MYAPP_CUSTOMIZATIONS}/js/css) }, expires: 3153600, cacheBust: headers["Bundle-Version"] }
The following example shows how you can define a JavaScript function that can later be called from within an alias resolver function:
(function() { /* Define transform function in global scope */ function transform(a, b, c) { a+(has("foo")?"/foo/":(has("bar")?"/bar/":c))+b }; return { baseUrl: '...', packages: [...], aliases: [ [/^(.*)\/backend\/(.*)$/, function($0,$1,$2){return transform($1, $2, '/backend/');}], ], }; })();