Импорт модуля перехвата JavaScript

У меня есть SPA (на Aurelia / TypeScript, но это не имеет значения), в котором используется SystemJS. Допустим, он работает на http://spa:5000/app.

Иногда он загружает модули JavaScript, такие как waterservice/external.js, по запросу с внешнего URL-адреса, например http://otherhost:5002/fetchmodule?moduleId=waterservice.external.js. Я использую SystemJS.import(url) для этого, и он отлично работает.

Но когда этот внешний модуль хочет импортировать другой модуль с простым import { OtherClass } from './other-class';, это (понятно) не работает. При загрузке SPA он смотрит на http://spa:5000/app/other-class.js. В этом случае мне нужно перехватить путь / местоположение, чтобы перенаправить его на http://otherhost:5002/fetchmodule?moduleId=other-class.js.

Примечание. Компиляция Typescript для waterservice/external.ts работает с поиском, потому что компилятор машинописного текста может легко найти ./other-class.ts. Очевидно, я не могу использовать абсолютный URL-адрес для импорта.

Как я могу перехватить загрузку модуля внутри модуля, который я импортирую с помощью SystemJS?

Один из подходов, который я уже тестировал, - это добавить отображение в конфигурацию SystemJS. Если я импортирую его как import { OtherClass } from 'other-class'; и добавлю сопоставление типа "other-class": "http://otherhost:5002/fetchmodule?moduleId=other-class", он работает. Но если этот подход хорош, как я могу добавить отображение динамически во время выполнения?

Также приветствуются другие подходы, такие как перехват универсального URL-адреса загрузки.


Обновить

Я попытался перехватить SystemJS, как предлагает artem вот так

var systemLoader = SystemJS;
var defaultNormalize = systemLoader.normalize;
systemLoader.normalize = function(name, parentName) {
    console.error("Intercepting", name, parentName);
    return defaultNormalize(name, parentName);
}

Обычно это ничего не меняет, но производит некоторый консольный вывод, чтобы увидеть, что происходит. К сожалению, это, похоже, что-то меняет, поскольку я получаю сообщение об ошибке Uncaught (в обещании) TypeError: this.has не является функцией внутри system.js.

Затем я попытался добавить сопоставления с SystemJS.config({map: ...});. Удивительно, но эта функция работает инкрементально, поэтому, когда я ее вызываю, она не теряет уже предоставленные сопоставления. Итак, я могу:

System.config({map: {
   "other-class": `http://otherhost:5002/fetchModule?moduleId=other-class.js`
}});

Это не работает с относительными путями (те, которые начинаются с . или ..), но если я помещу общие в корень, это сработает.

Я бы по-прежнему предпочел перехватить загрузку, чтобы иметь возможность обрабатывать больше сценариев, но на данный момент я понятия не имею, какая функция has отсутствует в приведенном выше подходе.


person ZoolWay    schedule 04.08.2016    source источник


Ответы (1)


как я могу добавить отображение динамически во время выполнения?

AFAIK SystemJS можно настроить в любое время, просто позвонив

SystemJS.config({ map: { additional-mappings-here ... }});

Если это не сработает для вас, вы можете переопределить loader.normalize и добавить там свое собственное сопоставление из идентификаторов модулей в URL-адреса. Что-то в этом роде:

// assuming you have one global SystemJS instance
var loader = SystemJS;

var defaultNormalize = loader.normalize;
loader.normalize = function(name, parentName) {
    if (parentName == 'your-external-module' && name == 'your-external-submodule') {
        return Promise.resolve('your-submodule-url');
    } else {
        return defaultNormalize.call(loader, name, parentName);
    }
}

Понятия не имею, будет ли это работать с машинописным текстом или нет. Кроме того, вам нужно будет выяснить, какие именно имена передаются в loader.normalize в вашем случае.

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

person artem    schedule 12.08.2016
comment
Из-за государственного праздника у меня не было времени рассмотреть это предложение прямо сейчас, но я сделаю это. Назначение награды, потому что в противном случае срок ее действия истек бы. Хотя я могу вернуться с вопросами;) - person ZoolWay; 16.08.2016
comment
Спасибо за понимание. Я обновил вопрос с обеих попыток. Вы знаете, почему перехват normalize вызывает ошибку в моем случае? - person ZoolWay; 18.08.2016
comment
Простите мою ошибку - defaultNormalize требует this аргумент: defaultNoramlize.call (loader, name, parentName); - person artem; 18.08.2016