如何使用`tsc`和`npm install`解决鸡/蛋情况?
Posted
技术标签:
【中文标题】如何使用`tsc`和`npm install`解决鸡/蛋情况?【英文标题】:How to resolve Chicken/Egg situation with `tsc` and `npm install`? 【发布时间】:2018-11-09 23:48:18 【问题描述】:所以我有标准的文件夹结构
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
。
但这并不是最方便的做法。
有没有人遇到过这个问题并找到了好的解决方案?
【问题讨论】:
我无法重现您在问题中描述的问题。我创建了一个新目录,将package.json
与您在问题中显示的规范放在一起,添加几个随机依赖项,然后运行npm install
没有任何问题。
您可能有 install
或 prepare
脚本执行了不应该执行的操作。你可以发布你的 package.json 吗?您可能应该使用prepublishOnly
。仅仅拥有bin
不会导致npm install
失败
【参考方案1】:
我不记得有这个问题,但至少在一个案例中我做了一些可以解决这个问题的事情。
我在根文件夹中放了一个 index.js,它运行 dist 中的实际依赖项。那么 npm 查找的 bin 是一个存在的文件,它不应该被吓坏。
当然,在运行 tsc 之前它不会工作。但它应该可以解决你的鸡和蛋的问题。
【讨论】:
当我尝试这个时出现的问题是,当 nodejs 脚本不在 PATH 中时,让 shell 函数正确/轻松地定位 nodejs 脚本。 我想最好的方法是这里接受的答案:***.com/questions/59895/…【参考方案2】:看起来preinstall
脚本是你需要的
将package.json
文件添加为
"scripts":
"preinstall" : "tsc ..." // < build stuff
参考https://docs.npmjs.com/misc/scripts
【讨论】:
对,但是我仍然没有 tsc 正常运行所需的 NPM 依赖项 通常 preinstall 脚本会做很多操作,我认为你应该在 bash(或带有 shebang 的 js)中正确编写它,比如“pre-install.sh”,然后在那个脚本中你可以做您需要的所有任务,例如安装“npm i tsc”和“tsc ...”【参考方案3】:我会签入一个文件./lib/cli
,文件内容是
#!/usr/bin/env node
require('../dist/cli.js')
然后正常运行 npm,然后运行 tsc。
【讨论】:
是的,但如果我有很多文件有点不方便,但我想这就是要走的路。【参考方案4】:绝对不是你的答案,但我通常更喜欢提交 javascript。
缺点:大量额外的 git 历史/膨胀。
我的观点:
最终您将生成一个 javascript 项目。所以应该测试 javascript 运行时,如果该项目也应该从 typescript 中使用,请测试生成的.d.ts
;
生成代码的 TSC 版本不应该是测试和消费者的另一个移动部分。您将针对许多 TSC 版本测试生成的输出,而不是您的源代码。
通过包含 .js 和 .d.ts 来减少“移动部分”边界,您获得的收益(= 可预测性)比失去的(git 历史膨胀)要多得多。
【讨论】:
【参考方案5】:@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"
...
【讨论】:
我使用git update-index --skip-worktree <file>
来“忽略”文件以上是关于如何使用`tsc`和`npm install`解决鸡/蛋情况?的主要内容,如果未能解决你的问题,请参考以下文章
如何引用由 NPM 包中 tsc 的“声明”选项生成的 TypeScript .d.ts 文件中声明的类型?