我正在尝试在Typescript应用程序中读取package.json。现在,我的tsconfig.json
包含以下内容:
"outDir": "dist",
"baseUrl": ".",
"rootDir": "src/",
当我编译它时,我得到File '/Path/to/package.json' is not under 'rootDir' '/Path/To/App/src/'. 'rootDir' is expected to contain all source files.
我理解这个问题,并且如果我要删除rootDir
,则所有内容都可以使用,除了dist
包含不需要的dist/src
。
这有什么解决方法?
答案 0 :(得分:14)
这是可能,事实证明,并不困难。
解决方案之所以不明显,是因为打字稿依靠rootDir
来决定输出的目录结构(请参见this comment from Typescript's bossman),并且仅包含代码可以导入输出或包中的依赖项。
rootDir
设置为项目的根目录,则会将package.json
发送到outDir
的根目录并可以导入。但是之后,您编译的src
文件将被写入outDir/src
。rootDir
设置为src
,则其中的文件将编译到outDir
的根目录。但是现在the compiler won't have a place to emit package.json
发出了“由于项目配置错误而产生的错误”(老板的话)。 Typescript项目由 tsconfig 文件定义,是自包含的,并且受其rootDir
有效地限制。这很不错,因为它符合封装原理。
您可以在各自的目录中和各自的tsconfig中拥有多个项目(例如,一个主库和一组lib)。它们之间的依赖关系使用Typescript Project References在tsconfig文件中声明。
我承认,术语“项目”是一个可怜的词,直觉上是指整个shebang,但是在这种情况下已经采用了“模块”和“包”。将它们视为“子项目”,这样会更有意义。
我们将src
目录和包含package.json
的根目录视为单独的项目。每个文件都有自己的tsconfig
文件。
将src
目录赋予其自己的项目。
./src/tsconfig.json
:
{
"compilerOptions": {
"rootDir": ".",
"outDir": "../dist/",
"resolveJsonModule": true
},
"references": [ // this is how we declare a dependency from
{ "path": "../" } // this project to the one at the root dir`
]
}
给根目录自己的项目。
./tsconfig.json
:
{
"compilerOptions": {
"rootDir": ".",
"outDir": ".", // if out path for a file is same as its src path, nothing will be emitted
"resolveJsonModule": true,
"composite": true // required on the dependency project for references to work
},
"files": [ // by whitelisting the files to include, TS won't automatically
"package.json" // include all source below root, which is the default.
]
}
运行tsc --build src
并加油!
这将构建src
项目。因为它声明了对根项目的引用,所以它也会构建该项目,但前提是该项目已过时。因为根tsconfig的目录与outDir
相同,所以tsc只会对package.json
(配置为要编译的一个文件)不做任何操作。
您可以通过将模块/库/子项目放在自己的子目录中并为其提供自己的tsconfig来隔离它们。
您可以使用Project References显式管理依赖关系,也可以模块化构建:
从链接的文档中:
期待已久的功能是用于TypeScript项目的智能增量构建。在3.0中,您可以将
--build
标志与tsc
一起使用。实际上,这是tsc
的新入口点,其行为更像是构建协调器,而不是简单的编译器。运行
tsc --build
(简称为tsc -b
)将执行以下操作:
- 找到所有引用的项目
- 检测是否为最新
- 以正确的顺序构建过时的项目
不用担心对在命令行上传递的文件进行排序-
tsc
会在需要时对它们进行重新排序,以便始终先构建依赖项。
加强组件之间的逻辑分离
以更好的新方式组织代码。
这也很容易:
src/tsconfig.json
即使您的根目录没有代码,此tsconfig也可以放在
所有通用设置都将被使用(其他设置将从其继承),并且
它将使简单的tsc --build src
能够构建整个
项目(并使用--force
从头开始构建它)。
{
"compilerOptions": {
"rootDir": ".",
"outDir": "../build/",
"resolveJsonModule": true,
"composite": true
},
// this root project has no source of its own
"files": [],
// but building this project will build all of the following:
"references": [
{ "path": "./common" }
{ "path": "./projectA" }
// include all other sub-projects here
]
}
src/common/tsconfig.json
由于 common 没有引用,因此导入仅限于其目录和npm_modules
中的目标。我相信,您甚至可以给它自己的package.json
来限制后者。
{
"compilerOptions": {
"rootDir": ".",
"outDir": "../../build/common",
"resolveJsonModule": true,
"composite": true
}
}
src/projectA/tsconfig.json
projectA 可以导入 common 。
{
"compilerOptions": {
"rootDir": ".",
"outDir": "../../build/libA",
"resolveJsonModule": true,
"composite": true
},
"references": [
{ "path": "../common" }
]
}
答案 1 :(得分:9)
我们可以将resolveJsonModule
设置为false并在*.json
内为typings.d.ts
声明一个模块,这将需要JSON文件作为模块,并且它将生成{{1 }}目录。
dist
monorepo\
├─ app\
│ ├─ src\
│ │ └─ index.ts
│ ├─ package.json
│ ├─ tsconfig.json
│ └─ typings.d.ts
└─ lib\
└─ package.json
app/typings.d.ts
declare module "*.json";
app/src/index.ts
// Import from app/package.json
import appPackageJson from '../package.json';
// Import from lib/package.json
import libPackageJson from '../../lib/package.json';
export function run(): void {
console.log(`App name "${appPackageJson.name}" with version ${appPackageJson.version}`);
console.log(`Lib name "${libPackageJson.name}" with version ${libPackageJson.version}`);
}
run();
内容package.json
现在,如果我们使用app/package.json
{
"name": "my-app",
"version": "0.0.1",
...
{
lib/package.json
{
"name": "my-lib",
"version": "1.0.1",
...
}
编译项目,则将获得以下tsc
目录结构:
dist
如果我们使用app\
└─ dist\
├─ index.d.ts
└─ index.js
运行它,我们将从node ./dist
和app
lib
信息中获取输出:
package.json
您可以在这里找到项目存储库:https://github.com/clytras/typescript-monorepo
答案 2 :(得分:2)
目前不可能。 Typescript编译器尝试保持目录结构。
例如,您的项目如下:
src/
shared/
index.ts
index.ts
package.json
tsconfig.json
您的tsconfig.json
包含:
{
"compilerOptions": {
"outDir": "./build",
"module": "commonjs",
"target": "es6",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noImplicitAny": true,
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true
},
"include": [
"src/**/*"
]
}
如您所见,文件不包含rootDir
属性,但是当您调用tsc
命令来编译项目时,输出将类似于:
build/
shared/
index.js
index.js
输出不包含src
文件夹,因为在我的代码中,我只是导入并在src
文件夹中使用,例如:
src/index.ts
import someName from './shared';
然后,build/index.js
如下所示:
...
const shared_1 = __importDefault(require("./shared"));
...
如您所见-require("./shared")
,这意味着它可以与build
文件夹结构配合使用。
当您导入“外部”模块时,您的“问题”出现了
import packageJson from '../package.json';
那么,“后退”动作-“ ../”会发生什么?如果您希望输出结构为:
build/
package.json
index.js
然后,它们如何与const packageJson = __importDefault(require("../package.json"));
一起使用。然后,Typescript编译器尝试保持项目结构:
build/
package.json
src/
index.js
对于一个monorepo项目,我认为您需要为每个库创建声明文件,然后在tsconfig文件中使用references
设置。例如:
./lib01
文件夹中,lib在其代码中导入./lib02
。 Tsconfig文件将类似于:{
"compilerOptions": {
"declarationDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*"],
"references": [ // here
{
"path": "../lib02"
}
]
}
tsconfig.json
{
"compilerOptions": {
"declarationDir": "dist",
"rootDir": "src",
"composite": true // importance.
}
}
答案 3 :(得分:0)
这取决于您阅读“ package.json”的方式和时间。您可以在运行时使用NodeJS“ fs”模块将其读取为文件,或者只需键入const package = require(“ package.json”)。
在第二种情况下,Typescript将在编译时在root目录中对其进行搜索(请参阅Typescript module resolution文档)。
您还可以使用“ rootDirs”属性代替“ rootDir”来指定根文件夹的数组。
答案 4 :(得分:0)
我通过使用符号链接解决了这个问题: 在窗口中:
cd src
mklink package.json ..\package.json
或在 linux 中:
cd src
ln -s package.json ../package.json