Delay executing defines until first require #183

Closed
fluidsonic opened this Issue Feb 13, 2012 · 3 comments

2 participants

@fluidsonic

Some good things about Advanced Module Loading are, that modules will be loaded asynchronously and on-demand.
On one side we split JavaScript code into separate modules to define and improve the project structure. On the other side it will only load these modules once they are actually needed, which leads to improved performance.

When r.js optimizes a project, it merges several modules into a single file and thus improves performance by reducing the number of files to load (less HTTP requests and so on).

r.js combines various modules into a single JavaScript file with multiple defines in it. But the downside is that require.js executes all of these defines directly (and thus "loads" these modules directly), even though no code actually required them.

This leads to three problems:

  • The application takes an unnecessary long time to load because lots modules which are still unused will be loaded at start-up time.
  • The modules may be loaded in the wrong order. They will be loaded in the order the optimizer wrote the defines to the output and not in the order the application's require calls took place, which may be essential.
  • The function passed to define may have side-effects, such as altering global variables or altering the DOM.

We had an issue with our CSS plugin, which creates one define during optimization for every CSS file imported. We expected the CSS to load when some code requires it and were suprised to see that all CSS was added to the DOM immediately on application start.

All of the problems listed above occurred here:

  • All the CSS was loaded at once and slowed down the page directly after loading the optimized JavaScript file.
  • The CSS did load in the order the optimizer wrote down the defines and not in the order the application requested the CSS files.
  • This caused stylesheet rules to be evaluated in the wrong order, because the functions passed to define immediately added CSS to the DOM.

I suggest to run the function passed to define only when the module was actually requested by a call to require. The define function should really just define a module and should not execute it immediately.

Example:

require(['css!a'], function() {
   require(['css!b'], function() {
      require(['css!c'], function() {
         // ...
      });
   });
});

This code expects to load the following CSS files to load in order: a.css then b.css then c.css.
The optimizer may get the order right in simple cases, but as soon as either the order of require calls is runtime-dependend or the dependencies become more complex, the order will no longer be maintained.

If this explanation is not enough to describe the problem, I will try to create a simple test case for the issue.

@fluidsonic

In reply to @jrburke's comment on #118:
We want the modules to be included in the build output, but we don't want them to be executed preliminary.

@jrburke
requirejs member

Assigning this for consideration in 1.1.

@jrburke jrburke closed this in dc90c89 May 18, 2012
@jrburke
requirejs member

This is fixed in the dev2.0 branch, will be part of the 2.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment