TypeScript 阻止文件成为模块?
Posted
技术标签:
【中文标题】TypeScript 阻止文件成为模块?【英文标题】:TypeScript stop file from becoming a module? 【发布时间】:2021-11-25 12:35:56 【问题描述】:我正在使用导入和导出,因为据说引用已过时。但是,我想编译成一个文件,并且我正在使用“系统”模块,但即使没有导出任何内容,它也会将所有内容都变成一个模块。如果导入了任何内容,则不执行代码,但如果没有导入或导出任何内容,则执行代码。我需要导入文件才能使用它们,但我不能,因为代码变成了模块函数。
这是我的 tsconfig.json:
"compilerOptions":
"module": "system",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": false,
"outFile": "PATH"
我的 TypeScript 代码:
import Button from "UI/Button";
new Button("Hello World!");
console.log("HELLO!");
编译后的代码变成这样:
System.register("Main/main", ["UI/Button"], function (exports_4, context_4)
"use strict";
var Button_1;
var __moduleName = context_4 && context_4.id;
return
setters: [
function (Button_1_1)
Button_1 = Button_1_1;
],
execute: function ()
new Button_1.Button("Hello World!");
console.log("HELLO!");
;
);
如果我删除导入并只保留 console.log:
console.log("HELLO!");
它会在没有导入的情况下删除所有内容,甚至是以前的模块,因为我猜它没有检测到它们正在被使用。
我假设我误解了导入/导出系统的工作原理?我希望能够运行函数和导入/导出文件,但到目前为止,我似乎只能导入/导出文件,而不能运行它们。我也希望将所有这些都编译到一个文件中。任何帮助将不胜感激!
【问题讨论】:
你在使用 webpack 吗?您需要通过在索引中执行import Button from "UI/Button";
来禁用 tree-shaking 或重新导出按钮。
@Win 我什至不确定 webpack 是什么。我只是想将我的 TypeScript 项目拆分为多个文件,然后将其编译为单个 .js 文件。我会研究一下 webpack 是什么,然后回复你。
你如何捆绑最终文件?你在用 ts-loader 吗?
@Win 我正在运行 TypeScript 编译器并在 html 页面中引用已编译的 .js 文件。我假设我错过了一步?
您应该能够在主 ts
文件中将 import Button from './Button';
替换为 export * from './Button';
,它会像您期望的那样编译,因为这意味着您的意思是使 Button 在模块外可用
【参考方案1】:
您需要从您的 HTML 文件中运行这些脚本,并使用 SystemJS(如在您的 tsconfig.json 中)调用它们。
import
或 export
的存在是 TypeScript 可以推断您是否正在编写 a script versus a module 的方式之一。编译输出的巨大变化来自 TypeScript 将您的文件解释为模块当且仅当它具有 import
或 export
语句。
模块背后的想法,来自 Mozilla 的cartoon introduction:
模块为您提供了一种更好的方式来组织这些变量和函数。使用模块,您可以将有意义的变量和函数组合在一起。
这会将这些函数和变量放入模块范围内。模块作用域可用于在模块中的函数之间共享变量。
但与函数作用域不同,模块作用域有一种方法可以使它们的变量也可用于其他模块。他们可以明确说明模块中的哪些变量、类或函数应该可用。
Modules 背后的整个想法是,您可以将作为UI/Button
模块(或您编写的任何其他模块)的一部分发生的加载推迟到您需要它时。 UI/Button
初始化只发生一次,并且只允许您访问 export
的变量、函数和类。 (也就是说,模块也可能具有“副作用”,例如您的console.log
:这些不是导出值,它们只是执行模块时发生的可见事物。)此外,每个模块都在其自己的命名空间中执行(这里是它自己的execute
函数),所以如果一个模块定义了一个counter
变量,它不会干扰另一个模块的counter
变量。
您选择了system
TypeScript 模块格式,也称为SystemJS。在这样做时,您注册让 SystemJS 管理您的模块加载,这将允许您调用 System.import
以从您发布的已编译 javascript 加载您的 Main/main
模块。那时您会看到您期望的输出,因为您已经特别要求了它。当您指定 outFile
时,您还可以选择 AMD(这也需要指定您的“入口点”)或“无”(这将是 prohibit import
and export
)。
一旦你对模块有了更好的理解,你就可以研究像 Webpack 这样的“捆绑器”。这些系统遍历您的所有模块(可能是一个文件,也可能是多个文件),并将它们捆绑到一个文件中,如您所描述的。你甚至可以告诉 Webpack 你打算将哪个模块作为入口点,它会在脚本加载后立即自动运行——就像老式的 JS 脚本一样。
【讨论】:
感谢您的详细回复。我让 Webpack 与系统模块一起工作。我什至将入口点设置为我的 main.ts 文件,但是,它似乎没有运行代码。它将它编译成我以前拥有的东西,除了它添加了一些东西,它似乎是通过自动生成的字典调用一个函数,但它从不调用从 .ts 生成的 main.js 文件。跨度> 我想通了!我将 ts-loader 用于 Webpack,在 tsconfig.json 中我使用了 CommonJS 模块。无需在 tsconfig.json 中使用 outFile,因为 Webpack 无论如何都会将代码编译成单个文件。现在它可以按我的需要工作!谢谢!以上是关于TypeScript 阻止文件成为模块?的主要内容,如果未能解决你的问题,请参考以下文章
三eggjs学习记录 - typescript声明放到types里面
解决 TypeScript 引入第三方包,报无法找到模块“XXX”的声明文件错误
解决 TypeScript 引入第三方包,报无法找到模块“XXX”的声明文件错误