How do I change the order in which Meteor loads Ja

2019-09-09 19:56发布

问题:

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?

回答1:

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



回答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.



回答3:

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



回答4:

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.