使用 Typescript 使用 Webpack 动态加载模块

Posted

技术标签:

【中文标题】使用 Typescript 使用 Webpack 动态加载模块【英文标题】:Dynamically load modules with Webpack using Typescript 【发布时间】:2017-08-22 13:35:03 【问题描述】:

我正在尝试构建一个支持插件的网络应用程序,环境是 Angular 2(到目前为止)、Typescript 2.1 和 Webpack 2。 我有一些扩展点(插槽),插件可以在其中绘制它们的内容:基本上我有一个组件,它能够托管一些在运行时已知的其他组件(有关这个想法,请参见“掌握 Angular 2 组件”第 10 章,以及SO + plunker 关于如何在运行时编译和“绘制”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

我在运行时使用来自 Webpack 的 System.import 导入模块,虽然我知道已弃用,但 AFAIK 它是使用 typescript 动态导入模块的唯一方法,因为 typescript 本身尚不支持 import(参考 @987654323 @)。 (有没有其他方法可以做到这一点?)

现在,只是为了测试系统,我使用下面的目录树将插件目录包含在应用程序的同一根目录(src 目录)中;注意这会导致 webpack 在编译时知道插件代码的存在,并将插件和应用程序打包在同一个包的集合中,这是为了测试插件架构能力的简化;这是文件夹树:

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

如果我用这种方式导入pluginA.plugin.ts System.import('relativePathToPluginA') 一切正常:系统能够加载和编译插件组件并使用它。

但是,在现实世界的场景中,插件在编译时一定是未知的,所以我使用 angular-cli 创建了一个新项目,并添加了 pluginA 目录,然后我在其中引用了它应用程序模块。然后我构建了项目并将 js 输出移动到一个文件夹中,比如说D:\pluginDist\。 然后我从上面的 loadPlugin 方法中引用了main.bundle.js,如下例所示(使用 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 模块。

【问题讨论】:

【参考方案1】:

Webpack.config.js 中更新以下代码。

resolver 用于加载相对于 src 根目录的文件,并通过解析 webpack.config.js 中的 app 文件夹,文件位于该文件夹可以通过如上所示的绝对路径访问。

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

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

在您的 system.import 中如下所示:app 是您的 src 文件夹中的文件夹

System.import('app/+ url').then(fileInstance=>           
    console.log(fileInstance);            
);

【讨论】:

以上是关于使用 Typescript 使用 Webpack 动态加载模块的主要内容,如果未能解决你的问题,请参考以下文章

使用 WebPack + TypeScript 定义导入的外部模块

使用源映射和 webpack 调试 typescript

如何使用 Webpack 对 Typescript 文件进行 Uglify

WebPack 5 与使用 React/Typescript 的 Web 工作者

Webpack 中 Typescript 的源映射(使用 webpack-dev-server 时看不到源映射)

vue不是构造函数错误,使用Typescript和webpack