使用 esm 时,带有 tsconfig-paths 的 ts-node 将不起作用

发布于 2025-01-16 12:18:23 字数 967 浏览 3 评论 0 原文

我无法弄清楚为什么 ts-node 在启用 esm 时无法解析别名

我做了一个小项目试图尽可能地隔离问题

package.json

{
  "type": "module"
}

tsconfig.json

{
  "compilerOptions": {
    "module": "es2020",                                
    "baseUrl": "./",                                  
    "paths": {
      "$lib/*": [
        "src/lib/*"
      ]
    },
  },
  "ts-node": {
    "esm": true
  }
}

test.ts

import { testFn } from "$lib/module"

testFn()

lib/module.ts

export function testFn () {
  console.log("Test function")
}

命令

ts-node -r tsconfig-paths/register src/test.ts

这是一个最小的存储库

I couldn't figure out why ts-node isn't resolving the alias when esm is enabled

I made a tiny project trying to isolate the issue as much as possible

package.json

{
  "type": "module"
}

tsconfig.json

{
  "compilerOptions": {
    "module": "es2020",                                
    "baseUrl": "./",                                  
    "paths": {
      "$lib/*": [
        "src/lib/*"
      ]
    },
  },
  "ts-node": {
    "esm": true
  }
}

test.ts

import { testFn } from "$lib/module"

testFn()

lib/module.ts

export function testFn () {
  console.log("Test function")
}

command

ts-node -r tsconfig-paths/register src/test.ts

Here's a minimal repo

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

╭ゆ眷念 2025-01-23 12:18:23

解决方案来自: https://github.com/TypeStrong/ts-node /discussions/1450#discussion-3563207

目前,ESM 加载器不处理 TypeScript 路径映射。为了使其工作,您可以使用以下自定义加载程序:

// loader.js
import {
  resolve as resolveTs,
  getFormat,
  transformSource,
  load,
} from "ts-node/esm";
import * as tsConfigPaths from "tsconfig-paths"

export { getFormat, transformSource, load };

const { absoluteBaseUrl, paths } = tsConfigPaths.loadConfig()
const matchPath = tsConfigPaths.createMatchPath(absoluteBaseUrl, paths)

export function resolve(specifier, context, defaultResolver) {
  const mappedSpecifier = matchPath(specifier)
  if (mappedSpecifier) {
    specifier = `${mappedSpecifier}.js`
  }
  return resolveTs(specifier, context, defaultResolver);
}

然后使用加载程序:
node --loader loader.js index.ts

注意:这仅适用于没有扩展名的模块说明符。例如, import /foo/bar 有效,但 import /foo/bar.js 和 import /foo/bar.ts 则无效。

请记住还要安装这些软件包:

"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.2",

更新:09/11/2023

新加载器将自动解析 index.(js|ts)

import { resolve as resolveTs } from 'ts-node/esm'
import * as tsConfigPaths from 'tsconfig-paths'
import { pathToFileURL } from 'url'

const { absoluteBaseUrl, paths } = tsConfigPaths.loadConfig()
const matchPath = tsConfigPaths.createMatchPath(absoluteBaseUrl, paths)

export function resolve (specifier, ctx, defaultResolve) {
  const match = matchPath(specifier)
  return match
    ? resolveTs(pathToFileURL(`${match}`).href, ctx, defaultResolve)
    : resolveTs(specifier, ctx, defaultResolve)
}

export { load, transformSource } from 'ts-node/esm'

示例:

Path: /src/modules/order/index.ts
Resolve: import orderModule from '@/modules/order';

更新:11/04/2024

对于节点版本20、我们需要设置arg:--experimental-specifier-resolution=node

node --experimental-specifier-resolution=node --loader ./loader.js src/main.ts

Solution from: https://github.com/TypeStrong/ts-node/discussions/1450#discussion-3563207

At the moment, the ESM loader does not handle TypeScript path mappings. To make it work you can use the following custom loader:

// loader.js
import {
  resolve as resolveTs,
  getFormat,
  transformSource,
  load,
} from "ts-node/esm";
import * as tsConfigPaths from "tsconfig-paths"

export { getFormat, transformSource, load };

const { absoluteBaseUrl, paths } = tsConfigPaths.loadConfig()
const matchPath = tsConfigPaths.createMatchPath(absoluteBaseUrl, paths)

export function resolve(specifier, context, defaultResolver) {
  const mappedSpecifier = matchPath(specifier)
  if (mappedSpecifier) {
    specifier = `${mappedSpecifier}.js`
  }
  return resolveTs(specifier, context, defaultResolver);
}

Then use the loader with:
node --loader loader.js index.ts

Caveat: This only works for module specifiers without an extension. For example, import /foo/bar works, but import /foo/bar.js and import /foo/bar.ts do not.

Remember to install these packages as well:

"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.2",

Updated: 09/11/2023

The new loader will automatically resolve the index.(js|ts):

import { resolve as resolveTs } from 'ts-node/esm'
import * as tsConfigPaths from 'tsconfig-paths'
import { pathToFileURL } from 'url'

const { absoluteBaseUrl, paths } = tsConfigPaths.loadConfig()
const matchPath = tsConfigPaths.createMatchPath(absoluteBaseUrl, paths)

export function resolve (specifier, ctx, defaultResolve) {
  const match = matchPath(specifier)
  return match
    ? resolveTs(pathToFileURL(`${match}`).href, ctx, defaultResolve)
    : resolveTs(specifier, ctx, defaultResolve)
}

export { load, transformSource } from 'ts-node/esm'

Example:

Path: /src/modules/order/index.ts
Resolve: import orderModule from '@/modules/order';

Updated: 11/04/2024

For the node version 20, we need to set the arg: --experimental-specifier-resolution=node

node --experimental-specifier-resolution=node --loader ./loader.js src/main.ts
猫烠⑼条掵仅有一顆心 2025-01-23 12:18:23

我建议使用 esno esno src/test.ts

I suggest to use esno esno src/test.ts

浪漫之都 2025-01-23 12:18:23

您可以使用 @bleed- believeer/path-alias 来执行您的 ESM 项目(ts-node 作为依赖项包含在内):

npm i --save @bleed-believer/path-alias

到使用ts-node执行源文件:

npx bb-path-alias ./src/test.ts

假设"outDir": "./dist",直接使用node执行转译代码(绕过ts-node):

npx bb-path-alias ./dist/test.js

如果如果您不想使用该库来执行转译后的项目,可以使用 swc (此转换器解析路径别名),或者您可以使用 tsc -alias 使用 tsc 转译项目后。

注意

我根据上次更新更新了库的使用方法。

You can use @bleed-believer/path-alias to execute your ESM project (ts-node is included as dependency):

npm i --save @bleed-believer/path-alias

To execute your source files with ts-node:

npx bb-path-alias ./src/test.ts

Assuming "outDir": "./dist", to execute your transpiled code directly with node (bypassing ts-node):

npx bb-path-alias ./dist/test.js

If you don't want to use the library to execute your transpiled project, you can use swc (this transpiler resolves the path aliases), or you can use tsc-alias after transpile your project with tsc.

Note

I updated the method of use the library according the last update.

从﹋此江山别 2025-01-23 12:18:23

现在有一个更好的打字稿执行节点模块“可以正常工作”。

https://tsx.is/

在此处输入图像描述

There's a better typescript execution node module that "just works" now.

https://tsx.is/

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文