【问题标题】:Omit "require" and "exports" from TypeScript emitted AMD dependencies从 TypeScript 发出的 AMD 依赖项中省略“require”和“exports”
【发布时间】:2017-12-03 19:13:56
【问题描述】:

鉴于以下 TypeScript 文件,

export = {};

tsc(带有"module": "amd")将发出:

define(["require", "exports"], function (require, exports) {
  "use strict";
   return {};
});

但是,我宁愿它发出

define([], function() {
    "use strict";
    return {};
});

...如果我明确导入它们,则仅包含requireexports,即

import relativeRequire = require("require");

有没有办法告诉 TypeScript 不要在发出的 AMD 模块中发出 requireexports(即要求它不要使用 CommonJS simplified wrapping)?

注意事项:

  • 我提出的输出完全符合AMD spec
  • 一个空的依赖数组是only way,模块具有零依赖(与省略依赖数组相反,这意味着requireexportsmodule依赖)。

2017 年 7 月 4 日更新: 看起来这实际上是 TypeScript GitHub 存储库中的一个未解决问题:https://github.com/Microsoft/TypeScript/issues/669

在实施之前,有什么实用的解决方法的想法吗? (或者,实际上有什么方法可以让 TypeScript 做到这一点?)

【问题讨论】:

    标签: typescript amd


    【解决方案1】:

    我认为您尝试做的事情没有实质性优势。对于任何不仅仅是玩具应用程序的应用程序,通过删除未使用的依赖项节省的任何执行时间都将与应用程序其余部分的执行时间相形见绌。 requireexports 都是虚拟模块,实例化成本很低。 (通过“虚拟”,我的意思是它们完全在您使用的 AMD 加载程序内部,不需要从网络或磁盘上的文件中获取任何内容。)我看到您提到的 issue 669 自 2014 年 9 月以来已打开并被视为“已接受” " 自 2015 年 4 月以来。似乎没有人受到如此严重的伤害以至于他们急于产生拉取请求。

    我不知道 TypeScript 会以何种方式开箱即用。我最近研究了 TypeScript 如何发出 define 调用,因为我需要将名为 "module" 的虚拟模块添加到依赖项列表中。 (如果您使用 Angular,您希望使用 module.id 将当前模块的 id 传递给 Angular,以便它可以解决诸如相对模板路径等问题。您可以使用 module.id 而不会出现 CommonJS 输出问题,但使用 AMD默认情况下,输出module 不包含在依赖项列表中。)我通过编写一个构建步骤解决了这个问题,该步骤在tsc 发出之后修改tsc 发出的代码。它使用修改依赖列表的正则表达式添加"module",并修改回调添加相应的参数。这对我有用,因为我正在添加。对于您正在尝试做的事情来说,这不是一个足够好的方法,因为您想删除依赖项,但在某些情况下删除它们会导致代码无效。

    对于解决方法,您可以使用Esprima 来检查tsc 生成的JavaScript 以及模块"require""exports" 的值是否未被内部代码使用工厂函数传递给define,然后从依赖列表中删除未使用的模块,并从传递给工厂函数的参数列表中删除相应的参数。这将是最通用的解决方案。 (除其他事项外,它与使用 AMD 加载程序在工厂函数内部提供的异步 require 调用(形式为 require([...], function (...) {}))兼容。)但编码此逻辑可能与编写代码一样复杂。产生一个拉取请求让tsc首先发出你想要的代码。

    【讨论】:

    • 我正在使用具有数千个 AMD 模块的相当大的应用程序,其中大约 1300 个在应用程序启动期间加载 - 因此必须是最初交付资产的一部分。我已经实现了大部分低挂载时间的性能提升,而减少资产大小(或许还可以消除不必要的虚拟模块)只是可以进行的小改进的长尾中的另一部分。
    【解决方案2】:

    需要

    你说:

    .. 并且仅在我明确导入时才包含 require 或 exports,即import relativeRequire = require("require");

    您不能使用require,除非它已经存在。所以它在那里很好。

    出口

    exports 在您导出某些内容时需要。如果您想像export = 那样进行根导出,那么 TypeScript 会将其映射到 return。但是对于export const foo = 123,它需要使用exports

    这样做并没有什么坏处,而且对性能的影响确实很小。

    【讨论】:

    • 这个项目从不使用exports,只是偶尔使用require。使用return ThisClass; 导出模块。 (它使用 Dojo 模块加载器,如果有的话。)
    猜你喜欢
    • 2020-03-04
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 2020-01-16
    • 2017-10-06
    相关资源
    最近更新 更多