Я пытаюсь создать веб-приложение, которое поддерживает плагины, среда 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, который не известен во время компиляции.