Cha*_*156 10 javascript typescript ecmascript-6 es6-modules
我正在尝试使用ES6模块解析将一个Typescript项目编译为JS,但似乎有些不对劲.
我的tsconfig.json看起来像这样:
{
"compilerOptions": {
"module": "es6",
"target": "es6",
"sourceMap": true,
"lib": ["es6"]
}
}
Run Code Online (Sandbox Code Playgroud)
我用两个模块构建了一个简单的测试用例.第一个模块(module1.ts)只导出一个常量:
export const testText = "It works!";
Run Code Online (Sandbox Code Playgroud)
第二个模块(main.ts)只是从第一个模块导入导出:
import { testText } from 'module1';
alert(testText);
Run Code Online (Sandbox Code Playgroud)
第二个模块(main.js)的输出文件包含在我的index.html中,带有type="module"
-Attribute:
<script src="main.js" type="module"></script>
Run Code Online (Sandbox Code Playgroud)
当我使用Firefox(dom.moduleScripts.enabled
在about:config中设置)和Chrome Canary(实验Web平台标志设置)进行测试时.在这两种情况下它都不起作用.
Typescript编译器似乎将TS import { testText } from 'module1';
语句转换为JS语句import { testText } from 'module1';
.(注意:两者完全一样)
正确的ES6 import语句将是:(
import { testText } from 'module1.js';
注意.js文件扩展名)如果我手动将文件扩展名添加到生成的代码中,它就可以工作.
我做错了什么或者Typescript "module": "es6"
设置不正常吗?有没有办法以这样的方式配置tsc:.js文件扩展名被添加到生成的import语句中?
JΛY*_*ÐΞV 17
作者注释:“此答案的发布日期与最初创建答案的日期不同。由于 TypeScript 的更改,我不得不写两次新答案。因为日期在这篇文章中非常相关,我已将它们包含在几个地方,以防答案变得陈旧。这将帮助读者知道我何时引用了我在下面写的任何技术的某些版本。
ESM 并不是一项容易融入 Node.js 的技术。当谈到用 TypeScript 语言编写 Node ES 模块时,在某个时间点,这实际上看起来永远不会发生。在我看来,某些项目似乎不想做他们现在已经做的事情来支持节点后端 RTE 中的标准。无论如何,让我们继续前进...
最初,当我回答这个问题时,我建议遇到此问题的人使用以下标志:
node --es-module-specifier-resolution=node
该标志起作用了,或者说是迄今为止最好的解决方案(或者直到 TS 4.7 Nightly Release 为止)。应该注意的是,根据您正在工作的环境和项目,这仍然是目前最好的解决方案。
此时此刻发生了很多变化:
在 v4.6 的 Nightly 版本中,TypeScript 添加了对新模块和 moduleResolution 说明符的支持,这些说明符(“显然”)在tsconfig.json
. 它们是在v4.6
每晚构建期间发布的,就在 v4.6 beta 发布之前不久,4.7 成为每晚构建。现在,v4.7
是测试版,并且v4.8
是新的夜间构建(我提到所有此版本的内容,只是为了确保您是最新的)。
"module": "NodeNext"
"moduleResolution": "NodeNext"
我这么说的原因是,新的 TSC 标志(又名 tsconfig 设置)在 中可用v4.6
,但是,如果您还记得的话,我在几段之前说过;TypeScript决定不在当前最新版本( typescript@latest
)版本中发布它们v4.6
。因此,它们将正式包含在 TypeScript 中,v4.7
不再处于测试版,并成为最新版本。
它们应该始终与"esModuleInterop": true
, (除非“Node.js”方面发生变化。“esModuleInterop”设置简化了对 ESM 的支持,并且某些节点模块需要它才能与新的 ESM 导入一起正常工作/导出模块系统。
这是 ESMtsconfig.*.json
配置模板,我将其添加为每个新项目的起点。
"compilerOptions": {
// Obviously you need to define your file-system
"rootDir": "source",
"outDir": "build",
// THE SETTINGS BELOW DEFINE FEATURE SUPPORT, MODULE SUPPORT, AND ES-SYNTAX SUPPORT
"lib": ["ESNext"],
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true, // Eases ESM support
"types": ["node"],
"allowSyntheticDefaultImports": true,
}
Run Code Online (Sandbox Code Playgroud)
module
&moduleResolution
说明符的支持因此,您可以使用几个不同的 TS 版本来支持新配置。您可以使用Beta或Nightly。下面的图表展示了 3 个可用版本。截至目前,typescript@latest
是 @ v4.6
,不支持新配置。
TS发布 | 版本 | NPM 执行命令 | 有支持吗? |
---|---|---|---|
TS最新 | v4.6 |
npm i -D typescript@latest |
不 |
TS测试版 | v4.7 |
npm i -D typescript@beta |
是的 |
TS 每晚 | v4.8 |
npm i -D typescript@next |
是的 |
您需要配置环境才能使用新的 TypeScript 版本。我显然无法记录编辑器的配置,但VS Code似乎是TypeScript最常见的配置,而VS 2022使用类似的配置。
在VS Code中,您将以下配置添加到工作区./.vscode/settings.json
文件中。
// "./.vscode/settings.json"
{ "typescript.tsdk": "./node_modules/typescript/lib",}
Run Code Online (Sandbox Code Playgroud)
(对于这个答案,它是 Node.js)
但为什么会这样呢?为什么我需要配置 RTE?这是怎么回事???RTE 不是什么都知道吗?
**但是我们不是已经配置了tsconfig.json
文件了吗?
我们需要告诉节点我们将执行 ECMAScript 模块,而不是 CommonJS 模块。我们可以通过两种不同的方式之一来完成此操作。
package.json
使用配置文件的“类型”字段来配置我们的文件package.json
。 // @file "package.json"
{
"name": "project-name",
"version: "2.4.16",
"type": "module", // <-- Lets env know this project is an ESM
// the rest of your package.json file configuration...
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以执行上面的一些操作,但是使用--input-type "module"
标志
最后,您可以执行我喜欢执行的操作,即使用ESM文件扩展名创建每个文件。在 js 中是这样.ejs
,在 typescript 中也是这样.ets
。
index.ets
,TSC 将发出index.ejs
.最后,重要的是您在编写“ES-Module”时了解导入的工作原理。我将列出一些注释,我认为这将是此信息的最佳格式。
导入文件时必须使用 JavaScript 文件扩展名。
ESM 导入是使用URI导入的,而不是使用“possix 文件路径”导入。CJS 模块的情况正好相反。
特殊字符必须采用百分比编码,例如带有 %23 的 # 和 ? 与%3F。
TypeScript 不会让您预先添加 MimeType,但 ESM 使用预先添加的数据类型,因此这是最佳实践。
例如,最佳实践是使用以下 URI 格式从 Node API 和库导入:
import EventEmitter from 'node:events';
const eEmit = new EventEmitter();
Run Code Online (Sandbox Code Playgroud)
Kei*_*ith 12
这是TypeScript 中的一个错误。
在短期内,您可以通过指定输出文件来解决它:
在main.ts
指定.js
扩展名和路径:
import { testText } from './module1.js';
alert(testText);
Run Code Online (Sandbox Code Playgroud)
这将module.ts
正确拾取,但输出包含.js
扩展名。
请注意,您还需要为本地文件添加前缀,./
因为“裸”模块名称保留供将来使用。
归档时间: |
|
查看次数: |
1129 次 |
最近记录: |