Решение первое: дерево загрузки. Стыкуем компоненты в JavaScript. Оптимизация структуры веб-страниц
Решение второе: загрузка через DOM-дерево
Решение третье: JSX + YASS
В качестве наиболее простого способа определить порядок загрузки модулей на конкретной странице можно предложить глобальный массив, содержащий в себе дерево зависимостей. Например, такое:
var modules = [
[0, 'item1', function(){
alert('item1 is loaded');
}],
[1, 'item2', function(){
alert('item2 is loaded');
}],
[1, 'item3', function(){
alert('item3 is loaded');
}]
];
В качестве элемента этого массива у нас выступает еще один массив. Первым элементом идет указание родителя (0 в том случае, если элемент является корнем и должен быть загружен сразу же), далее имя файла или его алиас. Последней идет произвольная функция, которую можно выполнить по загрузке.
Давайте рассмотрим, каким образом можно использовать данную структуру:
/* перебор и загрузка модулей */
function load_by_parent (i) {
i = i || 0;
var len = modules.length,
module;
/* перебираем дерево модулей */
while (len--) {
module = modules[len];
/* и загружаем требуемые элементы */
if (!module[0]) {
loader(len);
}
}
}
/* объявляем функцию-загрузчик */
function loader (i) {
var module = modules[i];
/* создаем новый элемент script */
var script = document.createElement('script');
script.type = 'text/javascript';
/* задаем имя файла */
script.src = module[1] + '.js';
/* задаем текст внутри тега для запуска по загрузке */
script.text = module[2];
/* запоминаем текущий индекс модуля */
script.title = i + 1;
/* выставляем обработчик загрузки для IE */
script.onreadystatechange = function() {
if (this.readyState === 'loaded') {
/* перебираем модули и ищем те, которые нужно загрузить */
load_by_parent(this.title);
}
};
/* выставляем обработчик загрузки для остальных */
script.onload = function (e) {
/* исполняем текст внутри тега (нужно тольно для Opera) */
if (/opera/i.test(navigator.userAgent)) {
eval(e.target.innerHTML);
}
/* перебираем модули и ищем те, которые нужно загрузить */
load_by_parent(this.title);
};
/* прикрепляем тег к документу */
document.getElementsByTagName('head')[0].appendChild(script);
}
/* загружаем корневые элементы */
load_by_parent();
Мы можем вынести загрузку корневых элементов в событие загрузки страницы, а сами функции — в какую-либо библиотеку, либо объявлять прямо на странице. Задавая на каждой странице свое дерево, мы получаем полную гибкость в асинхронной загрузке любого количества JavaScript-модулей. Стоит отметить, что зависимости в таком случае разрешаются «от корня — к вершинам»: мы сами должны знать, какие базовые компоненты загрузить, а потом загрузить более продвинутые.