【问题标题】:How to resolve Chicken/Egg situation with `tsc` and `npm install`?如何使用`tsc`和`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 失败

标签: node.js typescript npm npm-install tsc


【解决方案1】:

我不记得有这个问题,但至少在一个案例中我做了一些可以解决这个问题的事情。

我在根文件夹中放了一个 index.js,它运行 dist 中的实际依赖项。那么 npm 查找的 bin 是一个存在的文件,它不应该被吓坏。

当然,在运行 tsc 之前它不会工作。但它应该可以解决你的鸡和蛋的问题。

【讨论】:

  • 当我尝试这个时出现的问题是,当 nodejs 脚本不在 PATH 中时,让 shell 函数正确/轻松地定位 nodejs 脚本。
  • 我想最好的方法是这里接受的答案:stackoverflow.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; 来“忽略”文件
    猜你喜欢
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 2017-02-28
    相关资源
    最近更新 更多