我在我的项目中使用 react+typescript 有一些限制,这就是为什么我必须动态导入我的包(我的项目在带有 AMD 模块的 shell 项目中运行,没有我自己的启动,并更改项目文件的获取方式捆绑)。
由于我只能在运行时动态使用依赖模块,因此我不得不假设它们在构建和捆绑时是有效的。他们中的大多数是IIFE。
所以我使用了惰性动态导入。
类似的东西
import("somePolyfill");
这将由 TSC 翻译
new Promise(function (resolve_3, reject_3) { require(["arrayPolyfill"], resolve_3, reject_3); });
这将调用 IIFE 并执行 polyfill 或初始化任何窗口或全局变量,因此其余代码都知道这一点。
如果它返回一个模块或通过错误可以像正常的承诺一样处理然后捕获。
所以我创建了一个包装器
export class DepWrap {
public static Module: any = {};
public constructor() {
this.getPI();
this.getSomeModule();
}
public async getPI() {
DepWrap.Module["PI"] = 3.14;
}
public async getSomeModule() {
await import('somepath/somemodule').then(($package) => {
DepWrap.Module["somemodule"] = $package;
}).catch(() => {
window.console.log("Some Module error");
});
}
}
这被编译成
define(["require", "exports", "tslib"], function (require, exports, tslib_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var DepWrap = /** @class */ (function () {
function DepWrap() {
this.getPI();
this.getSomeModule();
}
DepWrap.prototype.getPI = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
DepWrap.Module["PI"] = 3.14;
return [2 /*return*/];
});
});
};
DepWrap.prototype.getSomeModule = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve_1, reject_1) { require(['somepath/somemodule'], resolve_1, reject_1); }).then(function ($package) {
DepWrap.Module["somemodule"] = $package;
}).catch(function () {
window.console.log("Some Module error");
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
DepWrap.Module = {};
return DepWrap;
}());
exports.DepWrap = DepWrap;
});
有了这个,我可以使用我的包装器中的所有依赖模块,每次我需要导入一个新的模块时,我都会创建另一个函数来将它添加到我的包装模块中。
import { DepWrap } from "wrapper/path";
const obj = new DepWrap(); // initialize once in the beginning of project so it would import all the dependencies one by one .
之后在所有文件中,我可以从包装器中导入我的模块
import { DepWrap } from "wrapper/path";
const { PI, somemodule} = DepWrap.Module;
我不确定代码是否也适用于您的场景,但我想稍微调整一下可能会对您的 useCase 派上用场。
另外:如果您正在编写单元测试用例,那么忽略模块并可以为此创建一个模拟,这样您就可以测试您的实际代码了。