我正在尝试使用纱线建立一个单体仓库。我对如何使用项目引用设置打字稿感到困惑,以便正确解决问题。
例如,如果我有类似的文件夹结构
/cmd
/client
我希望cmd
依赖于我可以拥有的client
:
cmd/tsconfig.json
:
{
"compilerOptions": {
"types": ["reflect-metadata", "jest"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"moduleResolution": "node",
"declaration": true,
"importHelpers": true,
"composite": true,
"target": "esnext"
"sourceRoot": "src",
"outDir": "dist"
},
"references": [
{
"path": "../client"
}
],
"include": [
"src/**/*"
]
}
带有package.json
{
"name": "cmd",
"version": "1.0.0",
"dependencies": {
"client": "^1.0.0",
}
}
在此模型中,cmd
和client
都使用在其tsconfig中设置的outDir
和sourceRoot
字段进行编译。这意味着他们所有已编译的javascript都进入dist/
和cmd/dist
client/dist
子文件夹中
如果现在我尝试像这样从client
到cmd
中引用一个类,
import Foo from 'client/src/foo'
IDE很高兴解决此问题,因为它似乎是通过typescript references
属性映射的。
但是,已编译的javascript可以归结为
const foo_1 = require("client/src/foo");
但是,实际内置的javascript是在client/dist/src/foo
中,因此在运行时这是行不通的。
另一方面,如果我不使用sourceRoots和outDirs并将javascript与打字稿文件内联在同一文件夹中,则一切正常(但使存储库变脏,并且需要自定义gitignores排除事物)
任何人都无法阐明如何使用纱线工作区正确设置打字稿3.x monorepo,从而使事情正常进行吗?
答案 0 :(得分:6)
我创建了一个Github Repository,以便更轻松地遵循以下代码描述:
TypeScript Project References
使编译包含多个较小的TypeScript项目的TypeScript项目成为可能,每个项目都有一个tsconfig.json
文件。 (来源:Project References Documentation)
我们有一个根tsconfig.json
文件,该文件仅管理其子项目。 references
属性指定目录,每个目录均包含有效的tsconfig.json
文件。如果现在使用--build
选项(tsc --build tsconfig.json
)构建项目,则我们指定了应编译的项目,但未指定构建顺序,项目应该被编译。
{
"references": [
{ "path": "./client" },
{ "path": "./cmd" }
],
"files": [],
"include": [],
"exclude": ["**/node_modules"]
}
要正确指定构建顺序,我们需要向references
文件中添加cmd/tsconfig.json
属性。这告诉编译器在编译client/
之前首先需要编译cmd/
:
cmd/tsconfig.json
:
{
"extends": "../tsconfig.packages.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"references": [
{
"path": "../client"
}
]
}
构建订单
client/
^
|
|
cmd/
最佳做法是每个子项目都有其自己的package.json
文件,该文件具有main
属性和name
集。在我们的示例中,两个包(cmd/
和client/
)都有一个main
属性,该属性指向TypeScript outDir
目录(index.js
中的cmd/dist/index.js
文件和client/dist/index.js
)。
项目结构:
tsconfig.json
cmd/
tsconfig.json
package.json
src/
index.ts
dist/ #artifacts
index.js
client/
tsconfig.json
package.json
src/
index.ts
dist/ #artifacts
index.js
client/packages.json
{
"name": "client",
"version": "1.0.0",
"main": "dist/index",
...
}
重要是我们将 client/
作为依赖项添加到 cmd/packages.json
,因此模块解析算法在TypeScript代码client/dist/index.js
中导入import Foo from 'client';
时可以找到cmd/packages.json
:
{
"name": "cmd",
"version": "1.0.0",
"main": "dist/index",
"dependencies": {
"client": "1.0.0" // important
}
}
cmd/src/index.ts
import Foo from 'client';
console.log(Foo())
node_modules
纱线设置简单。 Yarn将所有软件包添加到cmd/node_modules
下,而不是:
client/node_modules
workspaces
要启用纱线workspaces,请将private: true
属性和<root>/package.json
属性添加到<root>/package.json
文件中。
{
"private": true,
"workspaces": [
"cmd",
"client"
],
"name": "yarn_workplace",
"version": "1.0.0"
...
}
cmd/
client/
和symlinked
软件包位于<root>/node_modules/
目录下的cmd/
:
client/dist/index.d.ts
包将定义文件 var nest = d3.nest()
.key(function(d) {
return d.region;
})
.key(function(d) {
return d.date;
})
.rollup(function(leaves) {
return d3.sum(leaves, function(d) {
return parseInt(d.count, 10);
});
})
.entries(dataset)
用于类型信息,而不是直接使用TypeScript文件。答案 1 :(得分:-1)
我已经使用this repository中的Yarn Workspaces和Typescript在我的项目中使用了一些我一直使用的配置来设置了monorepo。
我不知道此设置是否可以解决您的问题,但您无需在Typescript配置中指定软件包。当您使用Yarn Workspaces时,它将在根node_modules
的工作空间包属性中定义的根package.json
中链接所有包:
"workspaces": {
"packages": [
"packages/**/*"
],
"nohoist": []
}
在yarn install
之后,根node_modules
具有client
和cmd
作为链接文件夹。
使用此配置,您可以简单地将任何软件包导入Workspace内的任何软件包。例如:
// cmd/src/index.ts
import { name } from 'client';
const otherName = 'cmd' + name;
console.log(otherName);