programing

Typescript 컴파일 중 상대 가져오기 문에 .js 확장자 추가(ES6 모듈)

cafebook 2023. 9. 25. 23:07
반응형

Typescript 컴파일 중 상대 가져오기 문에 .js 확장자 추가(ES6 모듈)

이는 사소한 문제로 보이지만 이 문제를 해결하기 위해 어떤 설정/구성을 사용해야 하는지는 그다지 명확하지 않습니다.

Hello World 프로그램 디렉터리 구조와 소스 코드는 다음과 같습니다.

디렉토리 구조:

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

index.ts:

import {HelloWorld} from "./HelloWorld";

let world = new HelloWorld();

HelloWorld.ts:

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

꾸러미의json:

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

합니다.tsc && node index.js다음 오류가 발생합니다.

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다가 ..js장()import {HelloWorld} from "./HelloWorld";하는 동안 타이프스크립트는 컴파일하는 동안 오류가 발생하지 않았습니다.드(v14.4.0)을 ..js

상황이 명확하기를 바랍니다.

을 하여 (tsconfig.json )와 가 .import {HelloWorld} from ./Helloworld;다로 됩니다.import {HelloWorld} from ./Helloworld.js;합니다.index.js일?

: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.

이 문제에 대한 해결책을 찾고 있는 동료 개발자들에게 우리가 발견할 수 있는 해결책은 다음과 같습니다.

  1. 사용하다.js가져오기에서 확장:

간단히 , 할 수 있습니다.".js"편집하는 동안 Typescript 파일의 Import 문에서 extension을 선택합니다.예:import {HelloWorld} from "./HelloWorld.js";

  1. 확장자 없는 파일 이름

가져오기 프로젝트에서 작업할 일괄 하고 할 수 ".js"생성된 자바스크립트에서 간단한 자동 스크립트를 통해 확장됩니다.와 같이 이 필요 없는다를 해야 할 .".js"적절한 MIME 유형을 가진 파일을 클라이언트에 전송합니다.

  1. regex를 사용하여 가져오기 문 일괄 바꾸기

옵션은 문을 하여 입니다..js내선예: https://stackoverflow.com/a/73075563/3330840 또는 이와 유사한 기타 답변.

업데이트된 사이드 노트:

처음에, 몇몇 답변들과 댓글들은 불필요한 주의 산만을 야기했고 가능한 해결책을 제시하는 대신 질문의 본래 목적을 회피하려고 했고, 저를 문제의 타당성을 방어해야 하는 상황으로 끌어들였습니다.이 질문에 대한 16k 이상의 조회수는 많은 개발자들이 이 문제에 직면했음을 보여주며, 이는 질문의 중요성을 입증합니다.따라서 더 이상의 주의 집중을 방해하지 않기 위해 원래의 사이드 노트가 댓글로 이동되었습니다.

VS 코드를 사용하는 경우 regex를 사용하여 경로를 바꿀 수 있습니다.

:(\bfrom\s+["']\..*)(["'])

:$1.js$2

이 솔루션은 이전 솔루션에서 영감을 얻었지만, 아래에 설명된 이유 때문에 이 솔루션이 더 잘 작동합니다.이 솔루션은 파일 가져오기를 구문 분석하는 대신 regex를 사용하기 때문에 완벽하지 않습니다.

npm 가져오기를 무시합니다.예:

import fs from 'fs'

여러 줄 가져오기를 지원합니다.예:

import {
  foo,
  bar
} from './file'

합니다.as수입품예:

import * as foo from './file'

큰따옴표와 큰따옴표를 지원합니다.예:

import foo from './file'
import foo from "./file"

내보내기를 지원합니다.내보내기 문서를 참조합니다.예:

export { foo } from './file'

nodejs CLI 를 하도록 설정하기 .node module resolution:

  • json을 .--experimental-json-modules
  • --experimental-specifier-resolution=node
node --experimental-specifier-resolution=node dist/some-file.js

에 대해 가치가 .--experimental-specifier-resolution=node 없음다를 할 수 .bin확장명이 없는 스크립트(예: package.json)bin분,"tsc",만,"tsc":"tsc.js"작동할 것입니다).

에 가(가) .bin다를 하는 데 .NODE_OPTIONS="--experimental-specifier-resolution=node" env

많은 분들이 지적해주셨듯이.TypeScript가 Import 문에 파일 확장자를 추가하지 않고 추가하지 않는 이유는 순수 자바스크립트 코드를 변환하는 것이 동일한 자바스크립트 코드를 출력해야 한다는 전제 때문입니다.

Import 문에 TypeScript가 파일 확장자를 적용하도록 플래그를 지정하는 것이 최선이라고 생각합니다.그러면 ESLint와 같은 린터는 그 규칙을 기반으로 자동 해결기를 제공할 수 있습니다.

TypeScript와 ESM에 문제가 있는 경우, 실제로 완벽하게 작동하는 작은 라이브러리가 있습니다.

npm install @digitak/tsc-esm --save-dev

교체tsctsc-esm스크립트에서 다음을(를)

{
   "scripts": {
      "build": "tsc-esm"
   }
}

마지막으로 다음을 실행할 수 있습니다.

npm run build

각 하고 esm을 했습니다..js아니면/index.js안전한 방법으로

fix-esm-import-

프로젝트에 사용하기 전에 테스트를 합니다.

(아마도) 더 나은 대답

이 아이디어를 바탕으로 의견에 제안된 더 나은 답변을 보려면 여기를 참조하십시오.

아직 테스트를 해보지는 않았지만, 아래의 원래 답변이 부족하고 링크된 답변이 더 나은 것 같습니다.확실하게 말할 수는 없지만 일단 확인해보는 것을 추천합니다.

나의 원답

수입 로 이 합니다..js 모든 가져오기에 Import는 extension다를든합니다..js 것을 할 수 n를 들어 regex기을 화"다.변경을 수행하기 전에 git(또는 다른 VCS) 로그를 확인하는 것이 좋습니다.VSCode에서 사용하는 정규화는 다음과 같습니다.

  • :(import .* from ".*(?!\.js)(.){3})".
  • :$1.js".

합니다 시킵니다..js내선 첫 번째 합니다.첫 번째 그룹은 마지막 인용문까지 부품을 캡처합니다. 대체 사용하여 의 첫 번째 .js확장명을 선택한 다음 확장명을 추가합니다.

린터 설정에 실패하면 이를 주기적으로 실행하고 확장자가 코드베이스로 넘어가지 않고 git 로그를 확인하여 가져올 수 없음을 확인할 수 있습니다.

npm, 누구?

npm i fix-esm-import-path

npmjs 또는 github에서 확인합니다.

8개의 별(하나는 제가 보낸 것)만 있지만 여러 프로젝트에서 사용하고 있으며 필요한 작업을 수행합니다.

npx fix-esm-import-path dist/your-compiled-entrypoint.js

하는 것을 .js으로..ts파일입니다. 타이프스크립트는 괜찮습니다.그러므로 당신은 다음과 같은 것을 갖게 될 것입니다..js당신의 빌드에 수입품이 있습니다.

예제 프로젝트:

project/src/
    index.ts
    mod.ts

index.ts:

import {something} from 'mod.js'

something()

빌드할 때:

project/build/
    index.js
    mod.js

입니다로 끝나는 을 갖게 .jsIDE와 컴파일러들이 불평하지 않을 겁니다

vScode를 사용하는 경우 확장 기능이 포함된 가져오기만 원하는 경우에는 이 문제를 살펴보십시오.
TS 컴파일러의 문제를 해결하지 않고 가져오기 경로를 단축하지 않도록 vScode를 만듭니다.

다른 해결책은 다음과 같은 것을 사용하는 것일 것입니다.resolveFullPaths선택.

불완전한 가져오기 경로(.js로 끝나지 않는 경로)를 완전히 확인된 경로(ECMAscript Modules 호환성의 경우)로 바꾸려고 시도합니다.

에 했습니다를 했습니다.tsc-alias일부 별칭 가져오기를 해결하려면(부모 가져오기를 사용하지 않는 것이 좋으나 상수 또는 유틸리티 함수와 같이 필요한 경우 별칭을 사용합니다.)resolveFullPaths가) 문제를 option option.

  1. tsc-alias

    yarn add -D -E tsc-alias
    
  2. tsconfig.js

    {
      "compilerOptions": {
        ...
      },
      "tsc-alias": {
        "resolveFullPaths": true,
        "verbose": false
      }
    }
    
  3. 하여 /를 호출합니다.tsc-aliastsc

    "scripts": {
        "compile": "tsc && tsc-alias"
    }
    

저는 보통 typescript 파일의 import statement에 .js 확장자를 사용하는데, 그것도 잘 됩니다.

가져오기 경로에 파일 확장명을 사용하지 않는 것은 nodejs뿐입니다.commonjs를 사용하지 않고 module을 사용하지 않기 때문에 nodejs를 사용하지 않습니다.따라서 가져오기 경로에서 .is 확장자를 사용해야 합니다.

TypeScript는 파일을 제공하기 위해 어떤 URI를 사용할지 알 수 없으므로 단순히 당신이 제공한 모듈 경로가 올바른지 신뢰해야 합니다.이 경우에는 존재하지 않는 URI에 대한 경로를 제공했지만 TypeScript는 이를 알 수 없으므로 이에 대해 어쩔 수 없습니다.

URI로 .js, 그러면 당신의 모듈 경로는 다음과 같이 끝나야 합니다..js 경우..js URI 에서를 하여 끝나지 ..js.

W3C는 URI에서 파일 확장자를 사용하지 말 것을 강력히 권고하는데, 이는 시스템을 진화시키는 것을 어렵게 하고 대신 콘텐츠 협상에 의존할 것을 옹호하기 때문입니다.

경로를 다시 쓰는 것은 TypeScript의 몇 가지 기본 설계 원리를 깨뜨릴 것입니다.한 가지 설계 원리는 TypeScript가 ECMAscript의 적절한 상위 집합이고 모든 유효한 ECMAscript 프로그램과 모듈은 의미론적으로 동등한 TypeScript 프로그램과 모듈이라는 것입니다.ECMAscript의 조각은 ECMAscript로 실행되는지 TypeScript로 실행되는지에 따라 다르게 동작하기 때문에 경로를 다시 쓰는 것은 이 원칙을 깨뜨릴 것입니다.상상해 보세요, 당신은 다음과 같은 코드를 가지고 있습니다.

./안녕하세요

export default "ECMAScript";

./hello.js

export default "TypeScript";

./메인

import Hello from "./hello";

console.log(Hello);

TypeScript가 제안한 것을 수행했다면 이는 ECMAscript로 실행하느냐 TypeScript로 실행하느냐에 따라 두 가지 다른 것을 인쇄할 것입니다. 그러나 TypeScript 설계 원칙에 따르면 TypeScript는 ECMAscript의 의미를 변경하지 않습니다.ECMA스크립트 조각을 TypeScript로 실행하면 ECMA스크립트로 실행할 때와 동일하게 동작해야 합니다.

저와 같은 솔루션을 사용하시면 됩니다.

파일: tsconfig.json

"compilerOptions": {
    "module": "commonjs",   ==> not required extension when import   
    "target": "ES6",
},

commonjs를 사용하기 때문에 패키지에서 "type": "module"을 제거해야 합니다.json

완료 : D

언급URL : https://stackoverflow.com/questions/62619058/appending-js-extension-on-relative-import-statements-during-typescript-compilat

반응형