我正在尝试构建一个支持插件的网络应用程序,环境是 Angular 2(到目前为止)、Typescript 2.1 和 Webpack 2。我有一些扩展点(插槽),插件可以在其中绘制它们的内容:基本上我有一个组件它能够托管在运行时已知的一些其他组件(有关该想法,请参见“掌握 Angular 2 组件”第 10 章,以及关于如何在运行时编译和“绘制”Angular 组件的SO + plunker )
这是我想要实现的目标:
// 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 导入模块,虽然我知道它已被弃用,但 AFAIK 它是使用 typescript 动态导入模块的唯一方法,因为import
typescript 本身还不支持(参考此处)。(有没有其他方法可以做到这一点?)
现在,只是为了测试系统,我使用下面的目录树将插件目录包含在应用程序的同一根目录(src 目录)中;注意这会导致 webpack 在编译时知道插件代码的存在,并将插件和应用程序打包在同一个包的集合中,这是为了测试插件架构能力的一个简化;这是文件夹树:
- 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
});
}
我不知道引用主边界是否正确(我肯定缺少一些 webpack 的概念)但它至少是构建工件,所以我试一试。这样我就有错误
Unhandled Promise rejection: Cannot find module 'D:\pluginDist\main.bundle.js'. ; Zone: angular ; Task: Promise.then ; Value:
我做的其他测试是
编译插件项目中的*.ts文件,完全跳过webpack,所以只需
tsc
在命令行中输入,并尝试导入pluginA.plugin.ts
编译结果,我遇到了和上面一样的错误。将 js 结果(来自 webpack 或来自普通 tsc 转换)放在开发 Web 服务器实际提供文件(.tmp)的文件夹中,然后通过相对路径引用它们:这会导致 webpack 在编译时停止,因为当然,它在打包时没有找到项目目录树中的文件。
现在不知道去哪里了,有什么建议吗??
我想要实现的是使用 webpack 和 typescript 动态加载,这是一个在编译时未知的 js 模块。