Typescript Compiler - 捆绑外部库

Posted

技术标签:

【中文标题】Typescript Compiler - 捆绑外部库【英文标题】:Typescript Compiler - Bundling external libraries 【发布时间】:2017-09-13 02:34:12 【问题描述】:

我正在尝试将我的 TypeScript“应用程序”捆绑到一个 javascript 文件中。

我没有使用任何捆绑程序,而是使用 TSC(使用 TypeScript 2.2)。除了我自己的 ts 文件外,我的应用程序还使用了外部模块,例如 immutablejs。

我阅读了所有可能的线程、文档,但我找不到仅使用 TSC 将外部模块(来自 node_modules )捆绑到我编译/转译的 javascript 文件中的方法。

您可以在下面找到我最新的代码/配置示例以及我的尝试结果。

tsconfig.json


    "compilerOptions": 
        "target":           "es5",
        "module":           "system",
        "removeComments":   true,
        "sourceMap":        true,
        "allowJs":          true
    

app.ts - 注意:./something.ts 已成功捆绑。

/// <reference path="../node_modules/immutable/dist/immutable.d.ts" />

import * as something from "./something";
import * as Immutable  from "immutable";

console.log( something.test );

const map1 = Immutable.Map(  a: 1, b: '2', c: 'cu' );
console.log( map1.get( 'a') )

1#:使用 tsc-bundle (https://www.npmjs.com/package/typescript-bundle)

这个方法不仅不绑定immutableJs而且抛出错误:require is not defined

var dragonfly = (function () 
  var main = null;
  var modules = 
      "require": 
          factory: undefined,
          dependencies: [],
          exports: function (args, callback)  return require(args, callback); ,
          resolved: true
      
  ;
  function define(id, dependencies, factory) 
      return main = modules[id] = 
          dependencies: dependencies,
          factory: factory,
          exports: ,
          resolved: false
      ;
  
  function resolve(definition) 
      if (definition.resolved === true)
          return;
      definition.resolved = true;
      var dependencies = definition.dependencies.map(function (id) 
          return (id === "exports")
              ? definition.exports
              : (function () 
                  if(modules[id] !== undefined) 
                    resolve(modules[id]);
                    return modules[id].exports;
                   else return require(id)
              )();
      );
      definition.factory.apply(null, dependencies);
  
  function collect() 
      Object.keys(modules).map(function (key)  return modules[key]; ).forEach(resolve);
      return (main !== null) 
        ? main.exports
        : undefined
  

  define("something", ["require", "exports"], function (require, exports) 
      "use strict";
      Object.defineProperty(exports, "__esModule",  value: true );
      exports.test = "oie";
  );
  define("app", ["require", "exports", "something", "immutable"], function (require, exports, something, Immutable) 
      "use strict";
      Object.defineProperty(exports, "__esModule",  value: true );
      console.log(something.test);
      var map1 = Immutable.Map( a: 1, b: '2', c: 'cu' );
      console.log(map1.get('a'));
  );
  //# sourceMappingURL=app.js.map
  return collect(); 
)();

#2 - 使用带有模块 = 系统的 TSC (tsc src/app.ts -m system --outfile build/app.js)

这个方法也没有绑定immutableJs,但是也抛出了错误:System is not defined

System.register("something", [], function (exports_1, context_1) 
    "use strict";
    var __moduleName = context_1 && context_1.id;
    var test;
    return 
        setters: [],
        execute: function () 
            exports_1("test", test = "oie");
        
    ;
);
/// <reference path="../node_modules/immutable/dist/immutable.d.ts" />
System.register("app", ["something", "immutable"], function (exports_2, context_2) 
    "use strict";
    var __moduleName = context_2 && context_2.id;
    var something, Immutable, map1;
    return 
        setters: [
            function (something_1) 
                something = something_1;
            ,
            function (Immutable_1) 
                Immutable = Immutable_1;
            
        ],
        execute: function () /// <reference path="../node_modules/immutable/dist/immutable.d.ts" />
            console.log(something.test);
            map1 = Immutable.Map( a: 1, b: '2', c: 'cu' );
            console.log(map1.get('a'));
        
    ;
);

#3 - 使用 tsc 和 module = amd (tsc src/app.ts -m amd --outfile build/app.js)

这个方法不仅不绑定immutableJs而且抛出错误:define is not defined。

define("something", ["require", "exports"], function (require, exports) 
    "use strict";
    exports.__esModule = true;
    exports.test = "oie";
);
/// <reference path="../node_modules/immutable/dist/immutable.d.ts" />
define("app", ["require", "exports", "something", "immutable"], function (require, exports, something, Immutable) 
    "use strict";
    exports.__esModule = true;
    console.log(something.test);
    var map1 = Immutable.Map( a: 1, b: '2', c: 'cu' );
    console.log(map1.get('a'));
);

结论:对于我的项目的未来来说,能够在不需要这些流行的打包工具(如 webpack、browserify、gulp 等)的情况下打包外部库非常重要......

有人可以帮助我吗?

提前致谢,

TF!

【问题讨论】:

只是好奇——你有没有理由拒绝 webpack 和 browserify 但愿意使用相对不为人知的 typescript-bundle?如您所见,typescript 不是捆绑器,它不会在输出中包含外部依赖项,除非它们都与您自己的代码同时编译在一起。 嗨,Artem,感谢您的回答...我拒绝的原因只有一个。我必须使用我创建的 webserver / watcher / task runner,你认为仍然是一个好主意/可能只使用其中一个(webpack、gulp、bower)作为捆绑器? 如果你只需要打包器,那么带有ts-loader 的webpack 是最明显的选择——除此之外你不需要其他任何东西。我也用systemjs-builder做捆绑,知道有人用rollup 再次感谢您的回答...我查看了 systemjs-builder,看起来非常简单。但问题是:您如何从浏览器中使用 JS?我的意思是如何使用捆绑包?它是否暴露在窗口对象级别? 还有它如何与 Typescript 一起工作?我需要先将 ts 编译成 js,然后运行 ​​trigger the bundler? 【参考方案1】:

刚刚注意到您的帖子和免责声明,我是 typescript-bundle 的作者。您可以将 ImmutableJS 与以下内容捆绑在一起。

tsc-bundle --project ./tsconfig.json --importAs immutable=Immutable

关于这个开关的一些文档here

这将创建一个额外的解析器,尝试从窗口对象解析不可变对象。如果您在页面中包含依赖脚本(通过 &lt;script&gt; 标记)并且需要在您的包中引用该全局名称(在这种情况下为不可变)(并且您需要使用 .d.ts 文件,则通常是这种情况从 @types/* 中提取,环境模块名为“不可变”)

以上行导致以下 resolve() 函数。

  function resolve(definition) 
      if (definition.resolved === true)
          return;
      definition.resolved = true;
      var dependencies = definition.dependencies.map(function (id) 
          return (id === "exports")
              ? definition.exports
              : (function () 
                  if(modules[id] !== undefined) 
                    resolve(modules[id]);
                    return modules[id].exports;
                   else if(id === "immutable") 
                    return window["Immutable"];
                   else 
                    try 
                      return require(id);
                     catch(e) 
                      throw Error("module '" + id + "' not found.");
                    
                  
              )();
      );
      definition.factory.apply(null, dependencies);
  

这适用于您在 npm @types/* 存储库中找到的大多数声明(假定为 UMD),并允许捆绑包有效地从环境中提取模块(全局变量名)。

希望对您有所帮助

【讨论】:

以上是关于Typescript Compiler - 捆绑外部库的主要内容,如果未能解决你的问题,请参考以下文章

浅析TypeScript Compiler 原理

如何在 TypeScript 中使用 Relay Modern(babel-plugin-relay 和 relay-compiler)?

TypeScript Compiler API:访问“this”参数的解析类型

如何让 TypeScript 从 node_modules 捆绑第 3 方库?

从 Visual Studio 捆绑 AngularJs TypeScript 应用程序

TypeScript Compiler API:如何在没有绝对路径的情况下获取类型的完全限定名称?