在Typescript编译过程中在相对导入语句上附加.js扩展名(ES6模块) [英] Appending .js extension on relative import statements during Typescript compilation (ES6 modules)

查看:898
本文介绍了在Typescript编译过程中在相对导入语句上附加.js扩展名(ES6模块)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是一个微不足道的问题,但是解决此问题需要使用哪些设置/配置并不是很明显.

This seems to be a trivial problem, but it is not very obvious what settings/configurations need to be used to solve this issue.

以下是Hello World程序的目录结构和源代码:

Here are the Hello World program directory structure and the source code:

目录结构:

| -- HelloWorldProgram
     | -- HelloWorld.ts
     | -- index.ts
     | -- package.json
     | -- tsconfig.json

index.ts:

import {HelloWorld} from "./HelloWorld";

let world = new HelloWorld();

HelloWorld.ts:

HelloWorld.ts:

export class HelloWorld {
    constructor(){
        console.log("Hello World!");
    }
}

package.json:

package.json:

{
  "type": "module",
  "scripts": {
    "start": "tsc && node index.js"
  }
}

现在,执行命令tsc && node index.js会导致以下错误:

Now, execution of the command tsc && node index.js results in the following error:

internal/modules/run_main.js:54
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'HelloWorld' imported from HelloWorld\index.js
Did you mean to import ../HelloWorld.js?
    at finalizeResolution (internal/modules/esm/resolve.js:284:11)
    at moduleResolve (internal/modules/esm/resolve.js:662:10)
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:752:11)
    at Loader.resolve (internal/modules/esm/loader.js:97:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:242:28)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:50:40)
    at link (internal/modules/esm/module_job.js:49:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

很明显,该问题似乎源于以下事实:在index.ts Typescript文件中,import语句(import {HelloWorld} from "./HelloWorld";)中没有.js扩展名. Typescript在编译过程中未引发任何错误.但是,在运行时,Node(v14.4.0)需要.js扩展名.

It is obvious that the problem seems to have been originated from the fact that in index.ts Typescript file there is no .js extension in the import statement (import {HelloWorld} from "./HelloWorld";). Typescript didn't throw any error during compilation. However, during runtime Node (v14.4.0) wants the .js extension.

希望上下文清楚.

现在,如何更改编译器输出设置(tsconfig.json或任何标志),以便在index.js文件中从Typescript到Javascript编译期间将本地相对路径导入(例如import {HelloWorld} from ./Helloworld;)替换为import {HelloWorld} from ./Helloworld.js;?

Now, how to change the compiler output setting (tsconfig.json or any flags) so that local relative path imports such as import {HelloWorld} from ./Helloworld; will get replaced by import {HelloWorld} from ./Helloworld.js; during Typescript to Javascript compilation in the index.js file?

注意: It is possible to directly use the .js extension while importing inside typescript file. However, it doesn't help much while working with hundreds of old typescript modules, because then we have to go back and manually add .js extension. Rather than that for us better solution is to batch rename and remove all the .js extension from all the generated .js filenames at last.

推荐答案

对于正在寻找此问题的解决方案的其他开发人员,我们遇到的可能的解决方法如下:

To fellow developers who are looking for a solution to this issue, the possible work-arounds we have come across are as follows:

  1. 对于新文件,可以在编辑时简单地在Typescript文件的import语句中添加".js"扩展名.示例:import {HelloWorld} from "./HelloWorld.js";

如果使用旧项目,而不是遍历每个文件并更新导入语句,我们发现通过简单的自动化脚本简单地批量重命名并从生成的Java脚本中删除".js"扩展名会更容易.但是请注意,这可能需要对服务器端代码进行较小的更改,才能为客户端提供这些具有正确MIME类型的无扩展名".js"文件.如果要避免这种情况,则可以改用正则表达式批量查找并递归替换import语句以添加.js扩展名.

If working with old projects, rather than going through each and every file and updating the import statements, we found it easier to simply batch rename and remove the ".js" extension from the generated Javascript via a simple automated script. Please note however that this might require a minor change in the server side code to serve these extension-less ".js" files with the proper MIME type to the clients. If you want to avoid this, you may instead want to use regular expression to batch find and replace the import statements recursively to add the .js extension.

旁注:

对于TS团队在解决此问题上的失败,似乎有一种趋势是试图从实际情况出发,而不是在实际情况中夸大此问题,并将其附加到一些捍卫设计的原则上.

Regarding the TS team's failure on resolving this issue, it appears that there is a tendency to try to blow up this issue out of context than what it really is and attach that to some design principles to defend.

但是,实际上,这仅仅是编译器如何不对称地处理扩展名的问题. Typescript编译器允许导入语句而无需扩展.然后继续添加".js".在翻译文件时将其扩展名扩展到相应的输出文件名,但是对于引用该文件的相应import语句,它忽略了已在文件名中添加了".js"的事实.翻译过程中的扩展名.上下文外URI重写原则如何捍卫这种不对称性?

However, factually this is nothing more than an issue with how the compiler deals asymmetrically with the extension. The Typescript compiler allows import statement without an extension. It then goes on to add ".js" extension to the corresponding output filename while the file is being translated, but for the corresponding import statements where this file is referenced it ignores the fact that it has added ".js" extension during translation. How can this asymmetricity be defended by the out of context URI rewriting principles?

在编译过程中,Typescript文件与生成的Javascript输出文件之间存在固定的一对一对应关系.如果引用的导入不存在,则编译器将引发错误.这些文件甚至无法编译!因此,出于上下文或无法编译的示例,提到其他冲突URI的可能性会使此类声明无效.

There is a fixed one to one correspondence between the Typescript file and the generated Javascript output file during compilation. If the referenced import does not exists, the compiler would throw an error. The files wouldn't even compile! So, out of context or non-compilable examples mentioning the possibility of other conflicting URIs invalidate such claims.

如果编译器只是生成了无扩展名的输出文件,那么它也将解决该问题.但是,这是否还会以某种方式违反有关URI重写的设计原则?当然,在这种情况下,可能存在其他设计原则来捍卫自己的立场!但是这样的固执不仅仅有助于进一步验证TS团队在此问题上的坚定或无知吗?

If the compiler simply generated extension-less output files it would also solve the issue. But, would that also somehow violate the design principle regarding URI rewrites? Certainly, in that case there could exist other design principles to defend the position! But wouldn't such stubbornness only help to further validate the adamancy or ignorance of the TS team on this issue?

这篇关于在Typescript编译过程中在相对导入语句上附加.js扩展名(ES6模块)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆