Псевдонимы пути в машинописном тексте не разрешаются правильно во время выполнения

Я использую VS Code, и сейчас я пытаюсь настроить псевдонимы для своего проекта машинописного текста.

Моя установка dev основана на nodemon и ts-node, код компилируется в папку dist.

Пока мне удалось заставить Typescript Hero управлять импортом с псевдонимами:

На данный момент моя структура папок такова:

.
└─┬ src
  ├──modules
  ├────Category
  ├────Ressource
  ├──shared
  ├────debug

// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "moduleResolution": "node",
        "pretty": true,
        "sourceMap": true,
        "target": "es6",
        "outDir": "./dist",
        "baseUrl": "./src",
        "paths": {
            "@shared/*": [
                "shared/*"
            ],
            "@modules/*": [
                "modules/*"
            ]
        },
        "resolveJsonModule": true,
        "esModuleInterop": true
    },
    "include": [
        "src/**/*.ts"
    ],
    "exclude": [
        "node_modules",
        "**/*.spec.ts",
        "**/*.test.ts",
    ]
}

И это первый неудачный импорт псевдонима.

//Server.ts file
import Print from '@shared/debug/Print.class';
import App from './App';

const MyApp: App = new App();

MyApp.ExpressApp.listen(MyApp.Config.ExpressPort, () => {
    Print.Log('Express server listening on port ' + MyApp.Config.ExpressPort);
});

Однако я получаю сообщение об ошибке: "Не удается найти модуль '@shared/debug/Print.class'" на "cross-env NODE_ENV=development nodemon ts-node ./src/server.ts".

И вот где я стою.

Теперь я прочитал несколько вопросов и ответов по SO, и кажется, что даже если бы мне удалось заставить псевдонимы работать в dev, он потерпел неудачу в производстве, так как я запускаю из папки Typescript src, и мои результаты построены в dist? Если да, есть ли способ исправить это? Большое спасибо

5 ответов

Решение

Проблема заключалась в разрешении псевдонимов путей к узлам во время выполнения. Даже если машинописный текст был выполнен во время выполнения ts-узлом, псевдонимы не могли быть разрешены узлом как есть. (Я думаю)

Но это была только верхушка айсберга. Я столкнусь с этим позже при моей настройке jest и во время выполнения JS.

Мне нужно было найти способ интерпретировать мои псевдонимы для каждой среды выполнения. Было несколько пакетов npm, но многие из них требовали дополнительных объявлений.

И я не хотел объявлять свои псевдонимы во всех файлах конфигурации, которые у меня были, и зависеть только от моего файла tsconfig.

После долгих испытаний осталось только два модуля узла для установки tsconfig-paths для выполнения машинописного текста на ts-узле. И @ef-carbon/tspm для преобразования моих псевдонимов в пункт назначения сборки.

npm i -D tsconfig-paths @ef-carbon/tspm

Для ts-узла сценарий был изменен как:

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

Для вашего скомпилированного js вам нужно только запустить:

ef-tspm

Для шутки нужен ts-jest, он у меня уже был, но настроен неправильно. Я использовал встроенный помощник, чтобы настроить свои пути. Мой файл конфигурации jest теперь выглядит так:

//jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig');
module.exports = {
    roots: ['<rootDir>/src'],
    globals: {
        'ts-jest': {
            tsConfig: 'tsconfig.json',
            diagnostics: {
                warnOnly: true,
            },
        },
    },
    clearMocks: true,
    coverageDirectory: 'coverage',
    testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
    moduleFileExtensions: ['js', 'json', 'jsx', 'node', 'ts', 'tsx'],
    testEnvironment: 'node',
    moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/' }),
    pathToJest: 'npm test',
    preset: 'ts-jest',
    testMatch: null,
};

Вот как мои скрипты выглядят в моем package.json

  "scripts": {
    "dev:ts": "cross-env NODE_ENV=development nodemon",
    "dev:js": "cross-env NODE_ENV=development npm run start:js",
    "staging": "cross-env NODE_ENV=staging npm run start:js",
    "production": "cross-env NODE_ENV=production npm run start:js",

    "test": "cross-env NODE_ENV=testing jest --runInBand",
    "test:debug": "npm run test --detectOpenHandles",

    "start:js": "npm run build && nodemon --config nodemon-js.json",
    "build": "npm run compile && npm run post:compile && npm run copyAssets",
    "compile": "tsc",
    "post:compile": "ef-tspm",
    "copyAssets": "copyfiles -e ./src/**/*.ts -e ./src/**/*sample* -e ./src/**/*.json -u 1 ./src/**/* ./dist/"
  },

Посмотрев, как это будет, я, вероятно, добавлю позже решение grunt/gulp. Но пока этого достаточно.

Я столкнулся с той же проблемой, и решение CrazyYoshi не работает должным образом в моем случае.

Я исправил это, поместив этот код в tsconfig.json:

      {
  "ts-node": {
    // Do not forget to `npm i -D tsconfig-paths`
    "require": ["tsconfig-paths/register"]
  }
}

Документация: https://typestrong.org/ts-node/docs/paths/

Вы используетеts-nodeиnodemonдля запуска вашего кода, поэтому вы должны добавить это в свойtsconfig.jsonфайл:

      {
    "ts-node": {
        "require": ["tsconfig-paths/register"]
    }
}

А затем установитьtsconfig-paths/registerкак зависимость от разработчиков.

      npm install --save-dev tsconfig-paths

Рекомендации

март 2023 г.

Просто потратил буквально часы, пытаясь заставить это работать. В конце концов я полностью отказался от ts-node и установил tsx , который работал прямо из коробки.

Судя по всему, это в конечном итоге появится в ts-node, хотя PR выглядит мертвым, так что кто знает:

https://github.com/TypeStrong/ts-node/pull/1585

Между тем, если вы действительно хотите использовать ts-node, вам может пригодиться следующее:

https://www.npmjs.com/package/@bleed-believer/path-alias

https://github.com/TypeStrong/ts-node/issues/1007

https://github.com/TypeStrong/ts-node/discussions/1450#discussioncomment-1806115

Я думаю, вы можете использовать пакет, называемый для решения этой проблемы.

Во-первых, установите его с помощью yarn, npm или pnpm, выберите тот, который вы используете.

Затем добавьте тот же псевдоним в свой package.jsonкак:

      {
  "_moduleAliases": {
    "@shared": "./src/shared",
    "@modules": "./src/modules"
  }
}

Наконец, для импорта module-alias/registerв вашей первой строке (это важно)!

      import 'module-alias/register'
// ... your other code

Это адрес г.module-aliasВы можете обратиться к нему.

Я надеюсь, что мой ответ поможет вам решить эту проблему.

Другие вопросы по тегам