46

When you make a project with the Meteor framework, it packages all the files together, but there doesn't seem to be a way to explicitly say "I want this file to be loaded before that one".

Let's say, for example, I have 2 javascript files: foo.js and bar.js.

The file bar.js is actually containing code depending one the one inside foo.js but Meteor is loading bar.js before foo.js, breaking the project.

  • In node.js I would simply use require('./bar') inside foo.js
  • In the browser, I would put a <script> tag pointing to foo.js and another, after, pointing to bar.js, in order to load the files in the correct order.

How can we do that in Meteor?

Coleman
  • 565
  • 7
  • 15
Jeremyfa
  • 662
  • 1
  • 7
  • 12
  • 1
    Meteor loads things in alphabetical order right now, as a simple hack you could rename a file to put it before/after another alphabetically. I know it lacks elegance, but that is the only way I know to influence load order. – lashleigh May 21 '12 at 22:44
  • 1
    Indeed. I was hoping there is another way to do this. Maybe exposing a browserify-like package would be a solution: https://github.com/substack/node-browserify . It would allow people to use node's style require() if they want to in their project. – Jeremyfa May 22 '12 at 08:47

4 Answers4

62

According to the Meteor documentation, files are currently loaded in this order:

  1. Files in [project_root]/lib are loaded first
  2. Files are sorted by directory depth. Deeper files are loaded first.
  3. Files are sorted in alphabetical order.
  4. main.* files are loaded last.

Source: http://docs.meteor.com/#structuringyourapp

user456584
  • 79,881
  • 11
  • 69
  • 105
agscala
  • 3,675
  • 5
  • 24
  • 25
  • Thanks, this logic is actually better than just sorting the files in alphabetic order as I expected. Should be enough to manage dependencies. – Jeremyfa May 24 '12 at 21:31
  • 3
    @JérémyFaivre yes, and if you use Meteor.startup(...) you can guarantee that everything has been loaded and the DOM is ready before you start using it. Have fun! – agscala Jun 04 '12 at 19:33
  • 3
    What if I am using an external script (like Google) and my scripts depend on it? – TigrouMeow Oct 22 '12 at 05:36
  • @JordyMeow you should be able to put it in lib/ - the ordering logic is now documented @ http://docs.meteor.com/#structuringyourapp – James Manning Oct 16 '13 at 03:06
  • What about code installed with meteorite? When do they get loaded? – Emre Kenci Jan 26 '14 at 11:15
  • I'd like more clarification on load order of packages. I'd assume that all packages are loaded before anything else, but I don't see that explicitly indicated...? – T3db0t Dec 31 '14 at 18:10
  • Meteor packaging defines loading order in dependencies of package.js so you usually doesn't care about it. It always being loaded before your main code also. If you still want to see it look inside package.js for statement like `api.use('reactjs:react@0.2.1', ['client', 'server']);`. That means reactjs:react package will be loaded _before_ this package, and it's dependencies even earlier. – Igor Loskutov Apr 05 '15 at 17:43
  • This has changed considerably in Meteor 1.3. [RTFM](http://docs.meteor.com/packages/modules.html#File-load-order) – Michael Cole Jun 09 '16 at 21:42
  • alphabetical order? wtf? Is this seriously the only way to control the load order of dependencies? – Jake Wilson Dec 05 '16 at 23:00
2

Not a solution for all scenarios, but I think ideally anything that is dependent on other code would be placed in a Meteor.startup function, to ensure everything is already loaded.

Chris
  • 766
  • 9
  • 18
-2

You can always us a JS loader like yepnope.js and add it to the client.js file. This works for me.

bitIO
  • 334
  • 2
  • 10
-2

I have a set of utility functions that I structured under common namespace (js global).

I.e.

// utils/utils.js
Utils = {};

and then in subfolders:

// utils/validation/validation.js
Utils.Validation = {};

// utils/validation/creditCard.js
Utils.Validation.creditCard = ... // validation logic etc

also I have bunch of code that uses Utils and it's subobjects.

Obviously, this structure doesn't work as Meteor load subfolders first.

To make it work as expected, I had to create /subfolder/subfolder/subfolder with meaningless names, and then shove root object in most deep subfolder, and branch objects in subfolders not so deep.

It is extremely counterintuitive for my taste and error-prone (suppose you have component that is even deeper in folder structure).

To address this issue, I used Q library with defers and promises. Solution still isn't clean as it makes you routine code repeating and checks but it gives you full control over the load order without messing with directory structure (hello to people who says you can organise meteor code as you want).

Example:

//utils.js
UtilsDefer = UtilsDefer || Q.defer();
UtilsDefer.resolve({
    // here some root utils stuff
});

//cards.js
// here we'll depend on Utils but don't want to care about directory structure
UtilsDefer = UtilsDefer || Q.defer(); // it will be a) already 
// resolved defer from utils.js, or b) new defer that will
// be resolved later in utils.js
UtilsDefer.then(function(Utils) {
    // do something with utils usage, or for instance add some fields here
    Utils.CreditCardDefer = Utils.CreditCardDefer || Q.defer();
    Utils.CreditCardDefer.resolve({
        // Credit card utils here
    })
});

//someOtherFile.js
// it will be pain to use sub-objects with this method though:
UtilsDefer = UtilsDefer || Q.defer();
UtilsDefer.then(function(Utils) {
    Utils.CreditCardDefer = Utils.CreditCardDefer || Q.defer();
    Utils.CreditCardDefer.then(function(CreditCard) {
        // do stuff with CreditCard _if_ you need to do it on startup stage   
    })
});

This is the example of rather narrow use case, as mostly you will be happy with handling these globals inside some user interaction callbacks or Meteor.startup where everything already initialised. Otherwise, if you want fine-grained control over initialisation order on very early stage, that could be a solution.

Igor Loskutov
  • 1,200
  • 2
  • 12
  • 24