-
Notifications
You must be signed in to change notification settings - Fork 15
Frequently Asked Questions
- My app works without the aggregator but fails when using it. How can I debug the problem?
- How can I decode loader generated aggregator requests?
- Why does my application take such a long time to load each time I restart the Aggregator?
- There seems to be too many loader generated Aggregator requests. How do I find out why?
- How can I ensure proper cache behavior with application updates?
The aggregator supports various query args that invoke debugging features. These query args are supported when debug or development mode are enabled. To use the query args, you need to be able to propagate query args specified in the URL for your application to the aggregator loader extension config. See the sample application's test.html and loaderConfig.js to see how this may be done. The following query args can be used to help debug your application:
- optimize
- Value can be
simple
(default),whitespace
, ornone
. Controls the level of optimization/minification performed on JavaScript and CSS files. - showFilenames
- If
true
, then each module in an aggregated response will be preceded by a comment identifying the name and location of the source file that provided the content. - noCache
- If
true
, then the aggregator will ignore any cached data and build the response from scratch. It will also include the Cache-Contrl:no-store header in the responses. - expandRequire
- If
log
(default =true
), then diagnostic information related to require list expansion will be written to the browser's JavaScript console - hasBranching
- If
false
(default =true
), then has! plugin branching will not be performed.
Alternatively, if you don't have access to an OSGi console, you can add developmentMode=true
or debugMode=true
to the aggregator properties file and restart the server. See Options for more details, and for descriptions of the features enabled by debug and development modes.
Note: depending on the console command processor installed in your OSGi framework, the command separator can be either a space or a colon. To see which separator you need to use, try entering the commands aggregator help
and aggregator:help
. The examples in this page all use the space separator, but if your command processor uses the colon, then you should adapt the examples accordingly.
You can also try enabling loader debugging by setting the dojo-error-api
and dojo-trace-api
features, as well as specifying loader trace logging options (see the trace
property in loaderConfig.js.
The following console commands are useful if the servlet is not running in development mode, or when editing certain type of content who's changes won't be recognized in development mode (e.g. inlined CSS or LESS imports).
aggregator clearcache <servlet-name>
aggregator validatedeps <servlet-name> clean
See Console Commands for a complete list of the Aggregator console commands and their descriptions.
Loader generated requests can be decoded in the browser client. Copy the URL you want to decode to the clipboard and then paste it into the console command below as indicated:
require.combo.decodeUrl("<paste URL here>")
Note that URL encodings are application version specific, so the client may be unable to decode a URL generated by a different version of the application.
See Decoding Aggregator request URLs for more details.
The Aggregator serializes the cache meta-data used to keep track of cache files approximately every 10 minutes (if necessary) and when the bundle Activator stop() method is called. If you are repeatedly starting and stopping your test environment without doing a proper shutdown of the framework (i.e. just terminating the JVM), then it is likely that the cache meta-data never gets serialized and the cache needs to be rebuilt from scratch every time the test environment is started. This situation can be verified by looking in the server trace logs for output similar to the following:
INFO: Cache metadata for aggregator not found. Removing existing cache files.
There are a few ways you can avoid this problem:
- Do a clean shutdown of the framework instead of killing the JVM to stop the test environment
- Wait at least 10 minutes after starting the test environment before killing the JVM
- Stop the Aggregator bundle with the
ss stop
command in the OSGi console prior to killing the JVM
Excessive loader generated Aggregator requests are usually caused by incomplete dependency expansion. As a result, one or more additional requests are needed to load nested dependencies, which can result in a cascade of requests resulting from dependency discovery.
The first thing to try to resolve the issue is to rebuild the dependency map. It may have become stale if you are making changes, particularly if development mode is not enabled. This can be done with the following OSGi console command:
aggregator validatedeps <servlet-name> clean
If that doesn't resolve the problem, then you can try to identify the module or modules whose dependencies are not being expanded by using the expandRequire=log
URL query arg. Search for the string NOT expanded
. Additional information provided with the log entry may give an indication as to why the module's dependencies were not expanded.
Finally, you can decode the Aggregator request URLs to determine which modules are being requested by the requests that follow your application generated request (the request generated by your require call). Knowing which modules the loader is requesting my help you identify which module's dependencies they belong to.
Note that the Aggregator will only expand the dependencies for modules that are specified as string constants in an array literal inside of a require call. So in the following example:
var a = "moduleA";
require([a, "moduleB"], function(a, b) {
moduleB's dependencies will be expanded but moduleA's will not.
Similarly, in the following example:
var deps = ["moduleA", "moduleB"];
require(deps, function() {
no dependency expansion will take place. Fortunately, the above use cases are rare because they also defeat static layer builders. If this type of usage is causing excessive Aggregator requests in your application and you can't change it (i.e. it's being done by third party code), then you can try to work around the problem by pre-loading the module(s) in question using the preloads query-arg, or by explicitly requiring the module(s) in a separate require call (if both require calls occur while processing the same event, then they should be combined into a single Aggregator request).
Another cause of incomplete dependency expansion is undefined features in has! loader plugin conditionals. For example, the module id dojo/has!foo?moduleA:moduleB
will result in moduleB
being loaded if foo
is undefined in the request. If foo
has a different value on the client, either because the value is updated after the request is made or the feature is being filtered using the featureFilter loader extension config property, then the loader will make additional requests to load moduleA
and its dependencies.
The Aggregator supports a cacheBust
config property. This can be set statically in the server-side AMD config file by your build process, or dynamically by server-side JavaScript code in the config (see the getBundleVersionsHash
property. The Aggregator keeps track of the cacheBust property and whenever it changes, the dependency map and server-side caches are cleared. The value of this property is also specified as the value of the cb
query arg in loader generated Aggregator requests, but may be overridden by client code, if desired, using the cacheBust
loader extension config property. There's also a cacheBust
option, which if specified, is combined with the cacheBust config property. The cacheBust option allows system administrators to change the cache bust value for a deployment without needing to modify the application. The only remaining consideration is the application generated Aggregator request for the boot layer. A common practice is to include in the request a cache bust query arg that contains a build generated timestamp. If your application's homepage is served by a servlet, then you can do something more dynamic.
By including cache bust query args that change when the application is updated, you can use the expires
config property to set a long term cache expiration time (e.g. one year) for Aggregator responses, avoiding the need for frequent cache validation requests to the Aggregator.