假设我有两个具有以下文件结构的项目
/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
的{{1}}。怎么做?
将其作为 NPM模块发布 - 绝对不想,这对于这样一个简单的用例来说是一种过度杀伤力。我只是 想要在两个项目之间共享一个文件。
使用project-b
- 不起作用,TypeScript抱怨
import '../project-a/lib.ts'
'lib.ts' is not under 'rootDir'. 'rootDir' is expected to contain all source files.
提升一级,以便涵盖tsconfig.json
和project-a
- 不能这样做,TypeScript配置对于这些项目略有不同。它也不方便,不想这样做。还有其他方法吗?
答案 0 :(得分:6)
这可以通过使用tsconfig.json中'CompilerOptions'的'paths'属性来实现
{
"compilerOptions": {
"paths": {
"@otherProject/*": [
"../otherProject/src/*"
]
}
},
}
下面是文件夹结构的屏幕截图。
下面是tsconfig.json的内容,该内容引用了其他ts-project
{
"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语句,用于引用其他项目的出口。
import { IntegrationMessageState } from '@qc/shared/states/integration-message.state';
答案 1 :(得分:4)
从Typescript 3.0开始,这可以通过“项目参考”来完成。
打字稿文档:https://www.typescriptlang.org/docs/handbook/project-references.html
我相信您将必须将lib.ts移入一个名为“ lib”之类的ts小项目中
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);
您现在可以从lib / lib.ts中的project-a和project-b中导入日志功能
// project-a/app.ts
// project-b/app.ts
import { log } from '../lib';
log("This is a message");
在您的智能功能开始工作之前,您现在需要使用以下命令来构建project-a和project-b:
tsc -b
首先将构建您的项目引用(在这种情况下为lib),然后再构建当前项目(project-a或project-b)。
打字稿编译器不会查看来自lib的实际打字稿文件。相反,它将仅使用在构建lib项目时生成的打字稿声明文件(* .d.ts)。
这就是为什么您的lib / tsconfig.json文件必须包含:
"declaration": true,
但是,如果使用Visual Studio代码中的F12键导航到project-a / app.ts中的日志功能的定义,则会显示正确的打字稿文件。 至少,如果您使用以下命令正确设置了lib / tsconfig.json
"declarationMap": true,
我创建了一个小的github存储库,演示了带有打字稿的项目引用示例:
答案 2 :(得分:0)
我认为@qqilihq的回复正确无误-尽管手动维护node_modules
目录的内容存在一些潜在的问题。
我很幸运使用lerna来管理此问题(尽管还有很多其他类似的工具,例如yarn workspaces似乎有点相似,尽管我没有使用过他们自己)。
我只是在前面说过,这可能对您正在谈论的内容有些沉重,但这确实为您的项目提供了很大的灵活性,可以在将来进行扩展。
使用这种模式,您的代码最终看起来像:
/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
设置为true 我对此的一般经验是非常积极的,因为一旦您了解了基本概念,其中就几乎没有“魔术”了,它只是一组共享目录的标准节点程序包。
答案 3 :(得分:0)
回答我自己的问题。有一些方法,但是没有简便的方法来共享TypeScript项目。
答案 4 :(得分:0)
我在后端和前端文件夹之间使用如下结构进行共享:
tsconfig.base.json:
{
"compilerOptions": {
"target": "es2019",
"baseUrl": "../src",
"moduleResolution": "node",
"alwaysStrict": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"removeComments": true,
"strictNullChecks": true,
"sourceMap": true
}
}
后端tsconfig:
{
"compilerOptions": {
"module": "commonjs",
"outDir": "../../build/backend"
},
"extends": "../../configs/tsconfig.base.json",
"references": [
{
"path": "../shared"
}
],
"paths": {
"shared": [
"shared/index"
]
},
"lib": [
"es2019"
],
}
前端tsconfig:
{
"compilerOptions": {
"outDir": "../../build/frontend",
"jsx": "react"
},
"extends": "../../configs/tsconfig.base.json",
"references": [
{
"path": "../shared"
}
],
"paths": {
"shared": [
"shared/index"
]
},
"lib": [
"es2019",
"dom"
]
}
共享的tsconfig:
{
"compilerOptions": {
"composite": true,
"declaration": true,
"outDir": "../../build/shared",
},
"extends": "../../configs/tsconfig.base.json"
}
运行该脚本的npm脚本:
"server-tsc": "cd src/backend && tsc -b -w"
"client-tsc": "cd src/frontend && tsc -b -w"
答案 5 :(得分:0)
似乎我们这里有一些选择:
(1)将两个项目都放在一个单库中,并使用TS项目引用使用@ThdK给出的答案
如果您不希望使用单色存储库,那就不好了
(2)使用Lerna-通过@metric_caution查看答案
如果您不愿意学习Lerna或不想将共享文件发布到npm,那就不好了
(3)创建一个共享的npm包
如果您不想将共享文件发布到npm,那就不好
(4)将共享文件夹放在项目A的“共享”目录中,并编写脚本以将共享文件夹中的文件从项目A复制到在git push上执行的项目B的共享文件夹,或者使用脚本来同步两个文件夹。
在需要复制/同步时,可以在此处手动执行脚本。复制/同步也可以在使用husky进行git推送之前完成,并且共享文件会在脚本中自动添加到git中。
由于我不希望有单色仓库,所以我也不想为了这样可悲的目的发布npm软件包,所以我自己选择了选项4。
答案 6 :(得分:-1)
在类似的场景中,我还想避免必须执行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
现在只需通过import { Whatever } from 'my-lib'
即可访问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 ignore设置, un - 使/node_modules
目录不会被提交。
这是一个干净的解决方案吗?可能不是没有。它解决了我的问题吗?是。我很高兴听到改进建议吗?绝对!
答案 7 :(得分:-1)
由于我是唯一从事 2 个需要共享代码文件夹的项目的开发人员,因此我在公共代码共享文件夹之间设置了 2 路 real time sync。
project A
- shared/ -> 2-way sync with project B
- abc/
project B
- shared/ -> 2-way sync with project A
- xyz/
这是一次性快速设置,但具有以下优点:
symlink
如果我想与其他团队成员合作,我可以提到使用这个同步工具作为项目设置的一部分。
答案 8 :(得分:-3)
我切换到deno
。 TypeScript 项目中的代码共享终于很容易了。