如何使用 `tsc` 和 `npm install` 解决 Chicken/Egg 的情况?
How to resolve Chicken/Egg situation with `tsc` and `npm install`?
所以我有标准的文件夹结构
dist/
src/
其中 src
有我的 .ts 文件,dist
有我的 .js 文件。
(我的 tsconfig.json 文件中有 "outDir":"dist"
,"includes"
设置为 'src'
)。
注意 'dist' 在我的 gitignore
文件中,所以它不在版本控制中,所以当它转到 Travis 或 CircleCI
,dist
文件夹中没有任何内容,直到我 运行 tsc
.
这是 问题 - 如果我先 运行 npm install
- 它会失败,因为我的 package.json 中有这个:
"bin":{
"foo" :"dist/cli.js" // dist/cli.js does not exist yet
}
但是如果我先 运行 tsc
- tsc 将缺少编译所需的依赖项,如果我 运行 npm install
.
我能想到的 解决这个问题的方法是先安装所有必需的 tsc
依赖项,然后 运行 tsc,然后 运行 npm install --production
.
然而,这并不是最方便的做法。
有没有人运行解决这个问题并找到好的解决方案?
我不记得有过这个问题,但至少在一个案例中我做了一些事情可以解决这个问题。
我在根文件夹中放置了一个 index.js,运行 是 dist 中的实际依赖项。然后 npm 查找的 bin 是一个存在的文件,它不应该惊慌失措。
当然,在 tsc 为 运行 之前,它不会起作用。但它应该可以解决您的先有鸡还是先有蛋的问题。
看起来 preinstall
脚本正是您所需要的
将您的 package.json
文件添加为
{
"scripts": {
"preinstall" : "tsc ..." // < build stuff
}
}
我会签入一个文件./lib/cli
文件内容是
#!/usr/bin/env node
require('../dist/cli.js')
并且 运行 npm 通常后跟 tsc。
绝对不是你的答案,但我通常更愿意提交 javascript。
缺点:大量额外 git history/bloat。
我的观点:
- 最终您正在制作一个 javascript 项目。因此,应该测试 javascript 运行时,如果该项目也应该从打字稿中使用,请测试生成的
.d.ts
;
- 生成代码的 TSC 版本不应成为测试和消费者的另一个移动部分。您将针对许多 TSC 版本测试生成的输出,而不是您的源代码。
- 通过包含 .js 和 .d.ts 来减少 "moving parts" 边界,您获得的(= 可预测性)远多于您失去的(git 历史膨胀)。
@wkrueger 的回答很接近。
这里的目标是只允许一个俗气的步骤工作,而不实际让它做任何有用的事情。这个俗气的步骤是在安装步骤中通过 bin
使文件引用可执行,这对于本地模块只对非转译的 JavaScript 有意义,至于转译的代码文件还不存在.幸运的是,这个俗气的步骤实际上并不关心文件是否可用,它只需要它存在就可以 chmod
它不会失败。
我解决这个问题的方法是简单地签入一个空的 dist/index.js
文件:
touch dist/index.js
然后将 dist
添加回 .gitignore
,因为您不想签入文件的真实版本。
在 NPM 6 中,我会在 package.json
中使用 preinstall
脚本,但这在 NPM 7 中已损坏,我碰巧正在使用它,我对转换为钩子不太感兴趣只是为了解决这个问题。如果您使用的是 NPM 6 或更早版本,preinstall
脚本将如下所示:
...
"scripts": {
"preinstall": "mkdir -p dist/ && touch dist/index.js"
}
...
所以我有标准的文件夹结构
dist/
src/
其中 src
有我的 .ts 文件,dist
有我的 .js 文件。
(我的 tsconfig.json 文件中有 "outDir":"dist"
,"includes"
设置为 'src'
)。
注意 'dist' 在我的 gitignore
文件中,所以它不在版本控制中,所以当它转到 Travis 或 CircleCI
,dist
文件夹中没有任何内容,直到我 运行 tsc
.
这是 问题 - 如果我先 运行 npm install
- 它会失败,因为我的 package.json 中有这个:
"bin":{
"foo" :"dist/cli.js" // dist/cli.js does not exist yet
}
但是如果我先 运行 tsc
- tsc 将缺少编译所需的依赖项,如果我 运行 npm install
.
我能想到的 解决这个问题的方法是先安装所有必需的 tsc
依赖项,然后 运行 tsc,然后 运行 npm install --production
.
然而,这并不是最方便的做法。
有没有人运行解决这个问题并找到好的解决方案?
我不记得有过这个问题,但至少在一个案例中我做了一些事情可以解决这个问题。
我在根文件夹中放置了一个 index.js,运行 是 dist 中的实际依赖项。然后 npm 查找的 bin 是一个存在的文件,它不应该惊慌失措。
当然,在 tsc 为 运行 之前,它不会起作用。但它应该可以解决您的先有鸡还是先有蛋的问题。
看起来 preinstall
脚本正是您所需要的
将您的 package.json
文件添加为
{
"scripts": {
"preinstall" : "tsc ..." // < build stuff
}
}
我会签入一个文件./lib/cli
文件内容是
#!/usr/bin/env node
require('../dist/cli.js')
并且 运行 npm 通常后跟 tsc。
绝对不是你的答案,但我通常更愿意提交 javascript。
缺点:大量额外 git history/bloat。
我的观点:
- 最终您正在制作一个 javascript 项目。因此,应该测试 javascript 运行时,如果该项目也应该从打字稿中使用,请测试生成的
.d.ts
; - 生成代码的 TSC 版本不应成为测试和消费者的另一个移动部分。您将针对许多 TSC 版本测试生成的输出,而不是您的源代码。
- 通过包含 .js 和 .d.ts 来减少 "moving parts" 边界,您获得的(= 可预测性)远多于您失去的(git 历史膨胀)。
@wkrueger 的回答很接近。
这里的目标是只允许一个俗气的步骤工作,而不实际让它做任何有用的事情。这个俗气的步骤是在安装步骤中通过 bin
使文件引用可执行,这对于本地模块只对非转译的 JavaScript 有意义,至于转译的代码文件还不存在.幸运的是,这个俗气的步骤实际上并不关心文件是否可用,它只需要它存在就可以 chmod
它不会失败。
我解决这个问题的方法是简单地签入一个空的 dist/index.js
文件:
touch dist/index.js
然后将 dist
添加回 .gitignore
,因为您不想签入文件的真实版本。
在 NPM 6 中,我会在 package.json
中使用 preinstall
脚本,但这在 NPM 7 中已损坏,我碰巧正在使用它,我对转换为钩子不太感兴趣只是为了解决这个问题。如果您使用的是 NPM 6 或更早版本,preinstall
脚本将如下所示:
...
"scripts": {
"preinstall": "mkdir -p dist/ && touch dist/index.js"
}
...