Динамическая загрузка модулей с помощью Webpack с использованием Typescript

Я пытаюсь создать веб-приложение, которое поддерживает плагины, среда Angular 2 (пока), Typescript 2.1 и Webpack 2. У меня есть несколько точек расширения (слотов), в которых плагины могут рисовать свой контент: в основном у меня есть компонент который способен размещать какой-либо другой компонент, известный во время выполнения (см. Идею в главе 10 «Освоение компонентов Angular 2» и SO + планкер о том, как компилировать и "отрисовывать" компонент Angular во время выполнения)

Вот чего я хочу добиться:

// in plugin.service.ts
loadPlugin(url)
{
    return System.import('absolute OR relative ?? plugin base path' + name)
           .then((pluginModule) => {
               const Plugin = pluginModule.default;
               // then use the plugin
    });
}

...

//content of the plugin file being imported
export default class HeaderButtonsPlugin {
    constructor() {}
    //useful things about the plugin
}

Я импортирую модули во время выполнения, используя System.import из Webpack, хотя я знаю, что это устарело, насколько я знаю, это единственный способ импортировать модули динамически с использованием машинописного текста, поскольку import еще не поддерживается самим машинописью (ссылка здесь). (есть ли другие способы сделать это?)

Теперь, просто для тестирования системы, я включил каталог плагинов в тот же корень приложения (каталог src), используя дерево каталогов ниже; помните, что это приводит к тому, что веб-пакет узнает во время компиляции о существовании кода плагина, и упаковать как плагин, так и приложение в один и тот же набор пакетов, это упрощение для проверки возможностей архитектуры плагина; вот дерево папок:

- src
    - app
        - core
            - plugin.service.ts
    - plugins
        - pluginA
            - pluginA.plugin.ts

таким образом, если я импортирую pluginA.plugin.ts с System.import('relativePathToPluginA'), все работает так, как ожидалось: система может загружать и компилировать компонент плагина, а также использовать его.

Но в реальном сценарии плагин не должен быть известен во время компиляции, поэтому я создал новый проект с помощью angular-cli и добавил каталог pluginA, а затем сослался на него в его app.module. . Затем я построил проект и переместил вывод js в папку, скажем, D:\pluginDist\. Затем я сослался на main.bundle.js из метода loadPlugin выше, как в приведенном ниже примере (с url = 'main.bundle.js')

loadPlugin(url)
{
    return System.import('D:\\pluginDist\\' + url)
           .then((pluginModule) => {
               const Plugin = pluginModule.default;
               // then use the plugin
    });
}

Я не знаю, правильно ли ссылаться на основную границу (мне точно не хватает некоторых концепций веб-пакета), но это, по крайней мере, артефакт сборки, поэтому я попробую. Таким образом, у меня есть ошибка Unhandled Promise rejection: Cannot find module 'D:\pluginDist\main.bundle.js'. ; Zone: angular ; Task: Promise.then ; Value:

Другие тесты, которые я сделал, были

  • транспилировать файлы *.ts в проекте плагина, вообще пропуская веб-пакет, поэтому просто набрав tsc в командной строке и попытавшись импортировать результат транспиляции pluginA.plugin.ts, у меня была та же ошибка, что и выше.

  • поместите результат js (как из веб-пакета, так и из простого преобразования tsc) в папку, где веб-сервер разработки фактически обслуживает файлы (.tmp), а затем ссылайтесь на них по относительному пути: это приводит к остановке веб-пакета во время компиляции, потому что из-за конечно, он не находит файлы в дереве каталогов проекта во время упаковки.

Теперь я не знаю, куда обратиться, у вас есть какие-либо советы??

Чего я хочу добиться, так это загрузить динамически, используя веб-пакет и машинописный текст, модуль js, который не известен во время компиляции.


person Luigi Dallavalle    schedule 29.03.2017    source источник


Ответы (1)


В Webpack.config.js обновите приведенный ниже код.

Resolver используется для загрузки файлов относительно корня src, и путем разрешения папки app в webpack.config.js файл в этой папке может доступ по абсолютному пути, как показано выше.

resolve: {
    extensions: ['.ts', '.js', 'css'],
    "modules": [
        "./node_modules",
        "src"
    ]
},

output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js',
        publicPath: 'dist/',
    }

И в вашем system.import, как показано ниже: где приложение — это папка внутри вашей папки src.

System.import('app/+ url').then(fileInstance=> {          
    console.log(fileInstance);            
});
person Sandip - Frontend Developer    schedule 13.07.2017