Как мне изменить порядок, в котором Meteor загружает файлы Javascript?
-
12-12-2019 - |
Вопрос
Когда вы создаете проект с помощью Meteor framework, он упаковывает все файлы вместе, но, похоже, нет способа явно сказать "Я хочу, чтобы этот файл был загружен раньше этого".
Допустим, например, у меня есть 2 файла javascript: foo.js
и bar.js
.
Файл bar.js
на самом деле содержит код, зависящий от того, что внутри foo.js
но "Метеор" загружается bar.js
до того, как foo.js
, ломающий проект.
- В node.js Я бы просто использовал
require('./bar')
внутриfoo.js
- В браузер, я бы поставил
<script>
тег, указывающий наfoo.js
и еще один, после, указывающий наbar.js
, для того чтобы загрузить файлы в правильном порядке.
Как мы можем это сделать в Метеорит?
Решение
Согласно документации Meteor, файлы в данный момент загружаются в таком порядке:
- Файлы в [project_root] /lib загружаются первыми
- Файлы сортируются по глубине каталога.Более глубокие файлы загружаются первыми.
- Файлы отсортированы в алфавитном порядке.
- главная.* файлы загружаются последними.
Другие советы
Не решение для всех сценариев, но я думаю, что в идеале все, что зависит от другого кода, должно быть помещено в функцию Meteor.startup, чтобы убедиться, что все уже загружено.
Вы всегда можете использовать загрузчик JS, такой как yepnope.js и добавьте его в файл client.js.У меня это работает.
У меня есть набор служебных функций, которые я структурировал в общем пространстве имен (js global).
Тоесть.
// utils/utils.js
Utils = {};
а затем во вложенных папках:
// utils/validation/validation.js
Utils.Validation = {};
// utils/validation/creditCard.js
Utils.Validation.creditCard = ... // validation logic etc
также у меня есть куча кода, который использует Utils и это подобъекты.
Очевидно, что эта структура не работает, поскольку Meteor загружает вложенные папки в первую очередь.
Чтобы все работало так, как ожидалось, мне пришлось создать /subfolder/ подпапку / subfolder с бессмысленными именами, а затем засунуть корневой объект в самую глубокую подпапку, а объекты ветвления - во вложенные папки не такой глубины.
На мой вкус, это крайне нелогично и подвержено ошибкам (предположим, у вас есть компонент, который находится еще глубже в структуре папок).
Чтобы решить эту проблему, я использовал библиотеку Q с отсрочками и обещаниями.Решение по-прежнему не является чистым, поскольку оно заставляет вас повторять обычный код и проверять его, но оно дает вам полный контроль над порядком загрузки, не вмешиваясь в структуру каталогов (привет людям, которые говорят, что вы можете организовать код meteor так, как хотите).
Пример:
//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
где все уже инициализировано.В противном случае, если вы хотите получить детальный контроль над порядком инициализации на очень ранней стадии, это может быть решением.