Как изменить порядок, в котором Meteor загружает файлы Javascript?

Когда вы создаете проект с фреймворком Meteor, он объединяет все файлы вместе, но, похоже, не существует способа явно указать "Я хочу, чтобы этот файл загружался до этого".

Скажем, например, у меня есть 2 файла javascript: foo.js и bar.js.

Файл bar.js на самом деле содержит код, зависящий от одного внутри foo.js, но Meteor загружает bar.js до foo.js, разбивая проект.

  • В node.js я просто использовал бы require('./bar') внутри foo.js
  • В браузере я бы поставил тег <script>, указывающий на foo.js, а другой, после, указав на bar.js, чтобы загрузить файлы в правильном порядке.

Как мы можем это сделать в Meteor?

Ответ 1

В соответствии с документацией Meteor файлы в настоящее время загружаются в следующем порядке:

  • Сначала загружаются файлы в [project_root]/lib
  • Файлы сортируются по глубине каталога. Сначала загружаются более глубокие файлы.
  • Файлы сортируются в алфавитном порядке.
  • main. * файлы загружаются последними.

Источник: http://docs.meteor.com/#structuringyourapp

Ответ 2

Не решение для всех сценариев, но я думаю, что в идеале все, что зависит от другого кода, будет помещено в функцию Meteor.startup, чтобы гарантировать, что все уже загружено.

Ответ 3

Вы всегда можете найти JS-загрузчик, например yepnope.js и добавить его в файл client.js. Это работает для меня.

Ответ 4

У меня есть набор функций полезности, которые я структурировал под общим пространством имен (js global).

т.е.

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

а затем в подпапках:

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

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

Также у меня есть куча кода, который использует Utils и его подобъекты.

Очевидно, что эта структура не работает как вложенные подпапки Meteor в первую очередь.

Чтобы он работал должным образом, мне пришлось создать/подпапку/подпапку/подпапку с бессмысленными именами, а затем перетащить корневой объект в самую глубокую подпапку и объекты ветвей в подпапках, которые не настолько глубоки.

Это очень противоречиво для моего вкуса и склонности к ошибкам (предположим, что у вас есть компонент, который еще глубже в структуре папок).

Чтобы решить эту проблему, я использовал библиотеку Q с defers и promises. Решение по-прежнему не является чистым, так как оно заставляет вас повторять и проверять обычный код, но он дает вам полный контроль над порядком загрузки, не вникая в структуру каталогов (привет людям, которые говорят, что вы можете организовать метеоритный код по своему усмотрению).

Пример:

//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   
    })
});

Это пример довольно узкого использования, так как в основном вы будете довольны обработкой этих глобалов внутри некоторых обратных вызовов взаимодействия с пользователем или Meteor.startup, где все уже инициализировано. В противном случае, если вы хотите получить мелкий контроль над порядком инициализации на очень ранней стадии, это может быть решением.