如何使用`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 没有任何问题。 您可能有 installprepare 脚本执行了不应该执行的操作。你可以发布你的 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 &lt;file&gt; 来“忽略”文件

以上是关于如何使用`tsc`和`npm install`解决鸡/蛋情况?的主要内容,如果未能解决你的问题,请参考以下文章

使用 npm run 时是不是使用了不同版本的 tsc?

如何引用由 NPM 包中 tsc 的“声明”选项生成的 TypeScript .d.ts 文件中声明的类型?

用于构建打字稿的 NPM 脚本不起作用

typescript 入门 01

删除 node_modules 后如何解决 npm install 问题

Visual Studio - 引擎盖下(NPM/Typescript)