fc1139f51d
Старт /lab грузит только каркас (~530KB) вместо ~2.9MB + three.js(~600KB):
- _loader.js — LabLoader.ensure(id): грузит файлы симуляции по манифесту +
three.js при необходимости; кеш по URL; САМОВОССТАНОВЛЕНИЕ (если open-функция
не определена после загрузки — грузит все ленивые файлы -> корректность
гарантирована независимо от точности манифеста)
- _sim_deps.js — сгенерированный манифест SIM_DEPS{id:{open,files,three}} +
LAB_LAZY_FILES; three:true только для crystal/orbitals/stereo/periodic
- _register-all.js — open-обёртка: LabLoader.ensure(id).then(rawOpen)
- lab-init.js openSim — обработка Promise от open() (lucide после init)
- lab.html — убраны 45 ленивых <script> + three.js из eager; каркас: registry,
loader, sim_deps, fx-движки, общие визуалы, graph.js (GRID для 15 сим)
Проверка: vm-harness (per-sim load, three only 3D, кеш, self-heal) ALL PASS;
инвариант owner-in-files для всех 40; нет утечки ленивых в eager; node --check OK.
В БРАУЗЕРЕ НЕ ПРОВЕРЕНО.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
77 lines
3.5 KiB
JavaScript
77 lines
3.5 KiB
JavaScript
'use strict';
|
|
/*
|
|
* LabLoader — ленивый загрузчик кода симуляций (контент-движок, Фаза 3).
|
|
*
|
|
* Тяжёлый код симуляций (~2.5 МБ) и three.js (~600 КБ) больше НЕ грузятся на старте.
|
|
* При открытии симуляции LabLoader.ensure(id) подгружает её файлы (по манифесту
|
|
* window.SIM_DEPS из _sim_deps.js) и, при необходимости, three.js — затем резолвит.
|
|
*
|
|
* Гарантия корректности (самовосстановление): если после загрузки указанных файлов
|
|
* глобальная open-функция (SIM_DEPS[id].open, напр. "_openPendulum") всё ещё не
|
|
* определена, грузятся ВСЕ ленивые файлы (window.LAB_LAZY_FILES). Поэтому ошибка в
|
|
* манифесте не может «сломать» симуляцию — в худшем случае грузится больше файлов
|
|
* (поведение как до Фазы 3). Манифест лишь оптимизирует объём загрузки.
|
|
*
|
|
* Все загрузки кешируются (по URL) и дедуплицируются.
|
|
*/
|
|
(function () {
|
|
var BASE = '/js/labs/';
|
|
var THREE_URL = 'https://cdn.jsdelivr.net/npm/three@0.149.0/build/three.min.js';
|
|
var _cache = {}; // url -> Promise
|
|
var _allLoaded = false;
|
|
|
|
function loadScript(url) {
|
|
if (_cache[url]) return _cache[url];
|
|
_cache[url] = new Promise(function (resolve, reject) {
|
|
var s = document.createElement('script');
|
|
s.src = url;
|
|
s.async = false; // сохранить порядок при добавлении нескольких сразу
|
|
s.onload = function () { resolve(url); };
|
|
s.onerror = function () { delete _cache[url]; reject(new Error('LabLoader: не удалось загрузить ' + url)); };
|
|
document.head.appendChild(s);
|
|
});
|
|
return _cache[url];
|
|
}
|
|
|
|
function ensureThree() {
|
|
if (typeof window.THREE !== 'undefined') return Promise.resolve();
|
|
return loadScript(THREE_URL);
|
|
}
|
|
|
|
function loadFiles(files) {
|
|
return Promise.all((files || []).map(function (f) { return loadScript(BASE + f); }));
|
|
}
|
|
|
|
function loadAllLazy() {
|
|
if (_allLoaded) return Promise.resolve();
|
|
var list = window.LAB_LAZY_FILES || [];
|
|
return loadFiles(list).then(function () { _allLoaded = true; });
|
|
}
|
|
|
|
// ensure(id): загрузить всё необходимое для симуляции id, вернуть Promise.
|
|
function ensure(id) {
|
|
var dep = (window.SIM_DEPS && window.SIM_DEPS[id]) || null;
|
|
if (!dep) {
|
|
// нет манифеста для id — безопасно грузим всё
|
|
return loadAllLazy();
|
|
}
|
|
var p = dep.three ? ensureThree() : Promise.resolve();
|
|
return p
|
|
.then(function () { return loadFiles(dep.files); })
|
|
.then(function () {
|
|
var openName = dep.open;
|
|
if (openName && typeof window[openName] !== 'function') {
|
|
if (window.console) console.warn('[LabLoader] самовосстановление для "' + id + '": ' + openName + ' не найдена после загрузки ' + JSON.stringify(dep.files) + ' — гружу все ленивые файлы');
|
|
return loadAllLazy();
|
|
}
|
|
});
|
|
}
|
|
|
|
window.LabLoader = {
|
|
ensure: ensure,
|
|
ensureThree: ensureThree,
|
|
loadScript: loadScript,
|
|
loadAllLazy: loadAllLazy
|
|
};
|
|
})();
|