Как изменить порядок, в котором 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?


person Jeremyfa    schedule 21.05.2012    source источник
comment
Meteor загружает вещи в алфавитном порядке прямо сейчас, в качестве простого хака вы можете переименовать файл, чтобы поместить его перед/после другого в алфавитном порядке. Я знаю, что ему не хватает элегантности, но это единственный известный мне способ повлиять на порядок загрузки.   -  person lashleigh    schedule 22.05.2012
comment
Конечно. Я надеялся, что есть другой способ сделать это. Возможно, решением будет предоставление пакета, подобного браузеру: github.com/substack/node-browserify . Это позволило бы людям использовать стиль node require(), если они хотят в своем проекте.   -  person Jeremyfa    schedule 22.05.2012


Ответы (4)


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

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

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

person agscala    schedule 24.05.2012
comment
Спасибо, эта логика на самом деле лучше, чем просто сортировка файлов в алфавитном порядке, как я ожидал. Должно быть достаточно для управления зависимостями. - person Jeremyfa; 25.05.2012
comment
@JérémyFaivre да, и если вы используете Meteor.startup(...), вы можете гарантировать, что все было загружено и DOM готов, прежде чем вы начнете его использовать. Повеселись! - person agscala; 04.06.2012
comment
Что, если я использую внешний скрипт (например, Google) и мои скрипты зависят от него? - person TigrouMeow; 22.10.2012
comment
@JordyMeow, вы должны иметь возможность поместить его в lib/ - логика упорядочения теперь задокументирована @ docs.meteor.com /#структурированиевашегоприложения - person James Manning; 16.10.2013
comment
Как насчет кода, установленного вместе с метеоритом? Когда они загружаются? - person Emre Kenci; 26.01.2014
comment
Я хотел бы получить больше разъяснений о порядке загрузки пакетов. Я бы предположил, что все пакеты загружаются раньше всего, но я не вижу, чтобы это было явно указано...? - person T3db0t; 31.12.2014
comment
Упаковка Meteor определяет порядок загрузки в зависимостях package.js, поэтому вам обычно на это наплевать. Он всегда загружается перед вашим основным кодом. Если вы все еще хотите увидеть это, загляните внутрь package.js и найдите выражение вроде api.use('reactjs:[email protected]', ['client', 'server']);. Это означает, что пакет reactjs:react будет загружен до этого пакета, а его зависимости еще раньше. - person Igor Loskutov; 05.04.2015
comment
Это значительно изменилось в Meteor 1.3. RTFM - person Michael Cole; 10.06.2016
comment
Алфавитный порядок? что? Это серьезно единственный способ контролировать порядок загрузки зависимостей? - person Jake Wilson; 06.12.2016

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

person Chris    schedule 23.05.2012

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

person bitIO    schedule 15.05.2013

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

I.e.

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

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

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

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

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

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

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

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

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

Пример:

//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, где все уже инициализировано. В противном случае, если вам нужен детальный контроль над порядком инициализации на очень ранней стадии, это может быть решением.

person Igor Loskutov    schedule 05.04.2015