如何将基于IIFE的JavaScript模块导入Angular TypeScript应用程序?

时间:2019-01-16 21:23:49

标签: javascript angular typescript webpack iife

因此,我有一个第三方SDK,写为基于Oldschool IIFE的模块。换句话说,它看起来像这样:

var ThirdPartySDK = (function() {
  var export = {};

  // Add some methods to export

  return export;
})();

然后您将希望通过在全局范围内引用它来使用它,

<html>
  <body>
    <script src="lib/ThirdPartySDK.js">
    <script>
      ThirdPartySDK.foo();
    <\script>
  <\body>
<\html>

我当然仍然可以以这种方式使用它,但这真的是Angular和TypeScript的最佳实践吗?有什么方法可以使用angular / TypeScript / webpack进行设置,以便可以使用正确的import语句?像这样:

import { ThirdPartySDK } from '../lib/ThirdPartySDK.js';
ThirdPartySDK.foo();

2 个答案:

答案 0 :(得分:1)

ThirdPartySDK的实际设置正确的导入语句的最佳方法是将脚本重构为导出该值的模块。以下代码段允许您使用显示的import语句:

export const ThirdPartySDK = {
    foo() { console.log('Doing foo'); }
};

对于大型库而言,重构并不总是那么容易,所以我看到了两种不涉及太多重构的方法:


1。导出ThirdPartySDK变量

您可以简单地通过导出当前的IThirdPartySDK变量(由IIFE返回),然后从IIFE文件中制作一个模块,然后按照显示的那样导入它:

export const ThirdPartySDK = (function() {
    var _export = {};

    // Add some methods to export

    return _export;
})();

请注意,如果您想获得有关ThirdPartySDK形状的一些有用信息,则必须在const声明中添加类型注释,如果要添加SomeType(请参见下文)还不存在,您必须自己编写:

export const ThirdPartySDK: SomeType = (function() {
// ...

这时,Typescript将开始抱怨IIFE表达式不能分配给SomeType;告诉SomeType使用关键字as的快速“解决方案”,告诉打字稿假装表达式是一个export const ThirdPartySDK: SomeType = (function() { // ... })() as SomeType; 类型的值:

<script>

2。保留interface SomeType { // SDK type shape goes here... } declare const ThirdPartySDK: SomeType; 标记并声明变量

另一种选择是保留脚本标记,不导入任何内容,以及declare the variable及其在打字稿中的预期类型:

(但在这种情况下,您可能必须自己提供类型定义)

sparse_categories = tf.convert_to_tensor([[1 if k == i else 0 for k in range(num_categories+1)] for i in range(num_categories+1)])
values = tf.cond(tf.size(values) > 0, lambda: values, lambda: [0])
values = tf.reduce_sum(tf.gather(sparse_categories, values))

答案 1 :(得分:1)

您可以使用带有eval的技巧将第三方SDK包装在TypeScript模块中。

让我们说ThirdPartySDK.js看起来像这样:

var ThirdPartySDK = (function () {
    var exports = {
        foo: function () { console.log("Hello, world!"); }
    };
    return exports;
})();

然后,您将创建一个ThirdPartySDK-wrapper.ts模块,看起来像这样:

import * as fs from 'fs';
const script = fs.readFileSync('../lib/ThirdPartySDK.js').toString();

global.eval(script);

//@ts-ignore
export default ThirdPartySDK;

必须使用@ts-ignore指令来防止TypeScript编译器抱怨找不到ThirdPartySDK变量的声明(在通过eval执行的脚本中声明)。

然后您可以通过包装器模块导入ThirdPartySDK:

import ThirdPartySDK from './wrapper';
ThirdPartySDK.foo();  // Console output: "Hello, world!" 

请注意,此包装器仅适用于在Node.js中运行的应用程序,因为它使用fs.fileReadSync来获取脚本的内容。

如果要在浏览器中使用它,则将需要其他方式来检索脚本。您可能会使用WebPack之类的框架将ThirdPartySDK脚本捆绑为字符串值,可以在包装器模块中require