Подтвердить что ты не робот

Импорт модуля перехвата 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 работает, потому что компилятор TypeScript может легко найти ./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);
}

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

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

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

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

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

4b9b3361

Ответ 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);
    }
}

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

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