简体   繁体   中英

How do I change the order in which Meteor loads Javascript files?

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 ?

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

并非所有情况的解决方案,但我认为理想情况下,任何依赖于其他代码的内容都应放置在Meteor.startup函数中,以确保所有内容均已加载。

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

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

Ie

// 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM