首页 > 解决方案 > Typescript 运行时模块加载(使用 webpack)和类似 dll 的后期绑定

问题描述

假设我有一组不断增长的不同模板可与 react 一起使用。每个模板extends React.Component并在其子项周围呈现精美的边框。

我希望从一些仅在运行时知道的数据中动态生成这样的模板(带有缓存等)。

在运行时,我可以计算包含模板的模块的名称。我可以将 URL 映射到服务器代码以提供 JavaScript 源代码并期望浏览器能够运行它。

我想我会用一种简单的方法隔离这段代码,类似于按名称加载 *.DLL 并调用其导出的符号。我在下面的猜测不起作用。

private async templateLoader():Promise<React.ComponentType>{
    const templateModuleName:string = this.props.api.getTemplateName(this.props.user);
    return (await import(templateModuleName)) as React.ComponentType;
}

我可以想象 JavaScript 像这样使用 require.js

var propsMappedFromStore=this.props;
//...
require(["api","user"],function(api,user){
  var templateModuleName = api.getTemplateName(user);
  require([templateModuleName],function(tt){
   propsMappedFromStore.updateTemplate(tt);
  })
})

但是 Typescript 和 Webpack 有可能吗?

我将如何要求/导入由表达式标识的模块?

标签: javascriptreactjstypescriptrequirejswebpack-2

解决方案


在处理 React 应用程序时,我遇到了这个问题。该应用程序分为多个模块。在这些模块中,有一组具有特定属性。这些模块不能参与 webpack 构建过程。它们在设计和构建时不存在。相反,我只知道他们出口的形状。

要使用这些模块,浏览器必须使用加载器。RequireJSAMD loader 是个不错的选择。

我花了很长时间才弄清楚如何让 WebPack 与异步加载很好地配合。这里的关键字是requirejs而不是requireimport

requirejs 的使用消除了 webpack.config.js 或任何其他魔法的任何魔法。下面的代码应该给你一个想法。使用语句requirejs(["locs/" + lang]…)会导致/{baseUrl}/locs/{lang}.js的 http 请求由 Web 服务器根据其智能处理。

import { getLanguage, IGreetingFormatStrings } from "./lociface";
import { defGeetings } from "./config";

function getGreetings(lang: string): Promise<IGreetingFormatStrings> {
    return new Promise((resolve) => {
        requirejs(["locs/" + lang]
            , (m) => { resolve(m.locGreetings as IGreetingFormatStrings); }
            , () => { resolve(defGeetings) }
        )
    });
}

export async function greeter(person: string): Promise<string> {
    const hours = new Date().getHours();
    const greetings = await getGreetings(getLanguage());
    if (hours > 6 && hours < 12) {
        return greetings.morning + person;
    }
    if (hours < 19) {
        return greetings.afternoon + person;
    }
    return greetings.night + person;
}

在此处输入图像描述


推荐阅读