Как использовать код между TypeScript проектами?
Скажем, у меня есть два проекта со следующей структурой файла
/my-projects/
/project-a/
lib.ts
app.ts
tsconfig.json
/project-b/
app.ts // import '../project-a/lib.ts'
tsconfig.json
Я хочу потреблять lib.ts
, расположенный в project-a
также из project-b
. Как это сделать?
-
Отпустите его как модуль NPM - абсолютно не хотите, чтобы, это излишний для такого простого использования. я просто
хотите поделиться одним файлом между двумя проектами.
-
Использовать import '../project-a/lib.ts'
- не работает, TypeScript жалуется
'lib.ts' is not under 'rootDir'. 'rootDir' is expected to contain all source files.
- Поместите
tsconfig.json
на один уровень вверх, чтобы он охватывал как project-a
, так и project-b
- не может этого сделать, конфигурация TypeScript немного отличается для этих проектов. Также это не очень удобно, не хочу этого делать.
Любые другие способы?
Ответы
Ответ 1
Начиная с Typescript 3.0 это можно сделать с помощью ссылок проекта.
Документы для машинописи: https://www.typescriptlang.org/docs/handbook/project-references.html
Я полагаю, вам придется переместить lib.ts в небольшой проект ts, который называется что-то вроде 'lib'
Проект lib должен иметь tsconfig, содержащий:
// lib/tsconfig.json
{
"compilerOptions": {
/* Truncated compiler options to list only relevant options */
"declaration": true,
"declarationMap": true,
"rootDir": ".",
"composite": true,
},
"references": [] // * Any project that is referenced must itself have a 'references' array (which may be empty).
}
Затем и в project-a, и в project-b добавьте ссылку на этот проект lib в свой tsconfig
// project-a/ts-config.json
// project-b/ts-config.json
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node"
// ...
},
"references": [
{ "path": "../lib" }
]
}
В проекте lib. Создайте файл index.ts, который должен экспортировать весь ваш код, которым вы хотите поделиться с другими проектами.
// lib/index.ts
export * from 'lib.ts';
Теперь, скажем, lib/lib.ts выглядит следующим образом:
// lib/lib.ts
export const log = (message: string) => console.log(message);
Теперь вы можете импортировать функцию log из lib/lib.ts как в project-a, так и в project-b.
// project-a/app.ts
// project-b/app.ts
import { log } from '../lib';
log("This is a message");
Прежде чем ваш intelissense заработает, вам нужно создать оба проекта project-a и project-b, используя:
tsc -b
который сначала создаст ссылки на ваш проект (в данном случае lib), а затем создаст текущий проект (project-a или project-b).
Компилятор машинописного текста не будет смотреть на фактические файлы машинописного текста из lib. Вместо этого он будет использовать только файлы объявлений машинописного текста (*.d.ts), сгенерированные при сборке проекта lib.
Вот почему ваш файл lib/tsconfig.json должен содержать:
"declaration": true,
Однако, если вы перейдете к определению функции журнала в project-a/app.ts с помощью клавиши F12 в коде Visual Studio, вам будет показан правильный файл машинописного текста.
По крайней мере, если вы правильно настроили свой lib/tsconfig.json с помощью:
"declarationMap": true,
Я создал небольшое репозиторий github, демонстрирующий этот пример ссылок на проекты с машинописью:
https://github.com/thdk/TS3-projects-references-example
Ответ 2
Это может быть достигнуто с помощью свойства 'paths' CompilerOptions в tsconfig.json
{
"compilerOptions": {
"paths": {
"@otherProject/*": [
"../otherProject/src/*"
]
}
},
}
Ниже приведен скриншот структуры папок.
![enter image description here]()
Ниже приведен контент tsconfig.json, который ссылается на другой ts-проект
{
"compilerOptions": {
"baseUrl": "./",
"outDir": "./tsc-out",
"sourceMap": false,
"declaration": false,
"moduleResolution": "node",
"module": "es6",
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
],
"paths": {
"@src/*": [ "src/*" ],
"@qc/*": [
"../Pti.Web/ClientApp/src/app/*"
]
}
},
"exclude": [
"node_modules",
"dist",
"tsc-out"
]
}
Ниже приведено утверждение импорта для ссылки на экспорт из другого проекта.
import { IntegrationMessageState } from '@qc/shared/states/integration-message.state';
Ответ 3
Я думаю, что @qqilihq находится на правильном пути с их ответом - Хотя есть отмеченные потенциальные проблемы с ручным обслуживанием содержимого node_modules
.
Мне посчастливилось справиться с этим с помощью lerna (хотя есть ряд других подобных инструментов, например, рабочие области пряжи кажутся чем-то похожими, хотя я сам ими не пользовался).
Я просто скажу заранее, что это может быть немного тяжелым для того, о чем вы говорите, но это дает вашему проекту большую гибкость, чтобы расти в будущем.
С этим шаблоном ваш код будет выглядеть примерно так:
/my-projects/
/common-code/
lib.ts
tsconfig.json
package.json
/project-a/
app.ts (Can import common-code)
tsconfig.json
package.json (with a dependency on common-code)
/project-b/
app.ts (Can import common-code)
tsconfig.json
package.json (with a dependency on common-code)
Общая теория здесь заключается в том, что инструмент создает символические ссылки между вашими внутренними библиотеками и каталогами node_modules
их зависимых пакетов.
Основные подводные камни, с которыми я столкнулся при этом:
-
common-code
должно быть установлено свойство main
и types
в файле package.json
-
common-code
должен быть скомпилирован, прежде чем любая из его зависимостей сможет положиться на него -
common-code
должен быть declaration
установлена верно в tsconfig.json
Мой общий опыт с этим был довольно положительным, поскольку, как только вы поняли основную идею, в ней очень мало "магии", это просто набор стандартных узловых пакетов, которые, как правило, совместно используют каталог.
Ответ 4
Отвечая на мой собственный вопрос. Существует несколько способов, но нет простого способа делиться проектами TypeScript.
Ответ 5
В аналогичном сценарии, где я также хотел избежать накладных расходов на выполнение выпуска NPM, я пошел на следующую структуру (после многих проб и ошибок и неудачных попыток):
/my-projects/
/node_modules/
/my-lib/
lib.ts
tsconfig.json
package.json
/project-a/
app.ts
tsconfig.json
/project-b/
app.ts
tsconfig.json
Основная идея состоит в том, чтобы переместить общий материал в каталог node_modules
над отдельными проектами (это использует механизм загрузки NPM, который начнет искать зависимости в текущем каталоге, а затем двигаться вверх).
Итак, project-a
и project-b
теперь могут получить доступ к lib просто через import { Whatever } from 'my-lib'
.
Примечания:
-
В моем случае my-lib
фактически используется только для общих типизированных (т.е. .d.ts
файлов в подкаталоге lib
). Это означает, что мне явно не нужно строить my-lib
, а мой my-lib/package.json
выглядит следующим образом:
{
"name": "my-types",
"version": "0.0.0",
"private": true,
"types": "lib/index"
}
-
В случае, если my-lib
содержит исполняемый код, вам, очевидно, нужно будет построить my-lib
, чтобы файлы .js
были сгенерированы и добавили свойство "main"
в package.json
, которое предоставляет основной .js
.
-
Самое главное: Несмотря на свое название, /my-projects/node_modules
только содержит пользовательский код, не зависимые установленные (они фактически находятся в отдельные проекты project-a/node_modules
и project-b/node_modules
). Это означает, что существует явный параметр игнорирования git, который un -значает каталог /node_modules
.
Является ли это чистым решением? Наверное, нет. Решила ли моя проблема? Да. Я рад услышать о предложениях по улучшению? Абсолютно!