从Github安装时自动构建NPM模块

Und*_*ion 45 javascript build github package npm

鉴于项目的lib/目录不应该被检入Git,因为它包含的文件是派生文件(来自构建过程).当(在开发为例)安装从项目的github上一包lib/目录将不存在,因此,如果包的package.jsonmain场点(例如)lib/index.js,包无法导入当编译,因为存储库中不存在这些文件因此在安装到的包中node_modules.这意味着需要构建软件包(就像在发布之前一样),只在本地这一次,以便将lib目录(或在构建过程中生成的任何其他文件)添加到模块的目录中.

假设文件的字段中有一个build脚本,是否可以将包配置为在仅从github安装它的情况下自动运行它?如果没有,从github安装时确保构建它的最佳方法是什么?package.jsonscripts

现在有prepublish,prepublishOnly而且prepare生命周期挂钩,但没有提供一个答案,这个问题,因为他们不允许任何方式的安装源进行区分.简而言之,是的,它们允许您构建安装,但它们不允许您仅从github构建安装.当人们从npm安装时,不仅没有理由强制构建,更重要的是,不会安装开发依赖项(例如babel,这对构建至关重要).

我知道有一个策略可以解决这个问题:

  • 回购/分支回购
  • 在本地建立
  • 删除lib/目录.gitignore并检入.
  • 从fork/branch安装模块
  • 当你准备好PR/rebase添加lib/dir .gitignore并从git中删除dir.

但这远非理想.我想这可以通过githook实现自动化.因此,每一个你掌握项目的人都会建立并推动到一个单独的分支.

NPM的Github上有一个封闭的问题没有解决方案 - 只有很多人想要一个解决方案.从这个问题可以清楚地看出,使用prepare不是答案.

我的用例是我正在开发一个用于许多其他项目的模块.我想使用最新版本的模块而不必在每次更新代码库时都向NPM推出一个版本 - 我宁愿在我准备好时推出更少的版本,但我仍然需要使用最新版本的lib在Github上.

注意:我也就此问题与NPM的支持联系,如果收到,我会添加他们的回复.

Cam*_*ind 22

prepare是正确的方法,但可能看起来坏了

如果您有一个包含源文件的存储库,但需要“构建”步骤才能使用它,
prepare那么在所有情况下都完全符合您的要求(从 npm 4 开始)。

prepare:在包被打包和发布之前,在npm install没有任何参数的本地运行,以及在安装 git 依赖项时运行。

您甚至可以将构建依赖项放入其中devDependencies,它们将在prepare执行之前安装。

这是我使用此方法的包的示例


有问题.gitignore-prepare似乎打破

这个选项有一个问题会吸引很多人。当准备依赖性,NPM和纱将保持只有那些在列出的文件files的部分package.json

人们可能会看到files默认包含所有文件并认为它们已完成。什么是容易错过的是.npmignore 大多覆盖files指令,如果.npmignore不存在,.gitignore来代替。

因此,如果您.gitignore像一个理智的人一样将构建的文件列在 中,并且不做任何其他事情,prepare看起来会损坏

如果您修复files为仅包含构建的文件或添加一个空的.npmignore,则一切就绪。

我的建议是设置files(或通过倒置.npmignore),以便实际发布的唯一文件是已发布包的用户需要的文件。恕我直言,无需在已发布的包中包含未编译的源代码。


Pio*_*ski 17

编辑:检测是否从git repo安装包

我没有正确理解这个问题.以下是我写的东西,但有点偏离主题.现在,如果你想运行build.js 从回购安装时:

回购中的文件:

 .gitignore
 .npmignore
 ThisIsNpmPackage
 build.js
 package.json
Run Code Online (Sandbox Code Playgroud)

.gitginore:

ThisIsNpmPackage
Run Code Online (Sandbox Code Playgroud)

.npmignore:

!ThisIsNpmPackage
Run Code Online (Sandbox Code Playgroud)

在package.json中:

"scripts": {
    "install": "( [ ! -f ./ThisIsNpmPackage ] && [ ! -f ./AlreadyInstalled ] && echo \"\" > ./AlreadyInstalled && npm install . && node ./build.js ) || echo \"SKIP: NON GIT SOURCE\""
}
Run Code Online (Sandbox Code Playgroud)

我们的想法是ThisIsNpmPackage在repo上提供文件,但不在npm包中.

安装钩子它只是一个bashy脚本来检查是否ThisIsNpmPackage存在.如果是,那么我们执行npm install .(这将确保我们有devDependencies.AlreadyInstalled生成文件以防止无限循环(npm install将以递归方式调用安装钩子)

发布当我这样做git push,并npm publish
注意NPM发布可以通过CI工具实现自动化- githooks

这个带文件的小黑客ThisIsNpmPackage使得源检测可用.

调用结果npm install dumb-package:

"SKIP:NON GIT SOURCE"

并执行 npm install https://github.com/styczynski/dumb-package

文件将被构建

问题

我们在这里面临的主要问题是以下几个问题:

  • 必须npm publish ...每次都做

    有时修复一个小错误太痛苦了,然后推送到回购并忘记在npm上发布.当我使用基于微服务的项目时,大约有5个独立子项目被分成模块,我发现问题的问题,修复它并忘记在每个地方发布我真的很烦人.

  • 不想lib进入回购,因为它来源于来源

  • 重新定位和合并更令人讨厌.

  • 没有乱 .gitgnore

    哎呀,我知道这个问题,当你有一个很复杂的文件,你必须包括在回购内但从不修改它们,或有时删除?那只是生病了.

编辑:npm钩子

正如@Roy Tinker所提到的那样,在安装时,包存在执行命令的能力.
它可以通过npm钩子实现.

"install": "npm run build"
Run Code Online (Sandbox Code Playgroud)

我们执行:

npm install https://github.com/<user>/<package>

编辑:
来自评论的OP问题:

但这将为每个从npm下载模块的人运行安装吗?这是非常有问题的,因为从npm下载模块的任何人都不会安装dev依赖项.用于构建应用程序的库 - babel等将不会被安装.

注意:但是如果您想要具有或不具有dev依赖关系的特定版本的包(生产/开发),您可以通过以下方式安装它:

npm install --only=dev

--only = {prod [uction] | dev [elopment]}参数将导致仅安装devDependencies或仅安装非devDependencies,而不管NODE_ENV如何.

我认为更好的解决方案是使用:

npm install <git remote url>
Run Code Online (Sandbox Code Playgroud)

然后在package.json里面指定:

"scripts": {
    "prepare": "npm run build"
}
Run Code Online (Sandbox Code Playgroud)

如果正在安装的软件包包含一个prepare脚本,则将安装其依赖项和devDependencies,并在打包和安装软件包之前运行prepare脚本.

例:

npm install git+https://isaacs@github.com/npm/npm.git
Run Code Online (Sandbox Code Playgroud)

在那里阅读npm文档: npm install

编辑:代理模块(高级技术)

这是一种不好的做法,但很高兴知道.

有时(如在Electron框架的情况下,您需要根据不同的条件安装其他外部包或资源/模块).

在这种情况下,使用代理的想法:

  • 您创建一个行为类似于安装程序的模块,并根据需要安装所有依赖项

在您的情况下,准备脚本就足够了,但我保留此选项,因为它有时可能有用.

想法是你编写一个模块并为它编写一个安装kook:

"scripts": {
    "install": "<do the install>"
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以放在那里:

npm install . && npm run build
Run Code Online (Sandbox Code Playgroud)

无论如何安装所有devDependencies(如前所述准备案例),但它有点黑客攻击.

如果你想在那里做真正的黑客攻击:

 "scripts": {
    "install": "curl -L -J -O \"<some_url>\""
 }
Run Code Online (Sandbox Code Playgroud)

使用-nix命令手动下载文件 curl

应该避免它,但是如果模块的每个平台都有巨大的二进制文件并且你不想全部安装它们,那么它是一个选项.

就像电子的情况一样,你已经编译了二进制文件(每个用于单独的平台)

所以,你希望人们作出install packageinstall package-linuxpackage-window等.

所以你提供了自定义install脚本package.json

{
  ...
  "scripts": {
     "install": "node ./install_platform_dep.js"
  }
}
Run Code Online (Sandbox Code Playgroud)

然后安装时moduleinstall_platform_dep.js 脚本将被执行.在install_platform_dep.js你里面:

// For Windows...
if(process.platform === 'win32') {
    // Trigger Windows module installation
    exec('npm install fancy-module-windows', (err, stdout, stderr) => {
         // Some error handling...
    }
} else if ... // Process other OS'es
Run Code Online (Sandbox Code Playgroud)

纯粹以手动方式安装所有内容.

注意:这种方法再次适用于依赖于平台的模块,如果您使用它,则可能是您的代码存在设计问题.

循环整合

我想到的是我真正用于日志时间的解决方案(使用CI服务自动构建).

大多数CI服务的主要目的是在推送到分支机构或使用repo执行其他操作时测试/构建/发布代码.

这个想法是你提供设置文件(如travis.yml.gitlab-ci.yml),工具负责其余部分.

如果您真的不想将lib包含到项目中,只需信任CI即可完成所有操作:

  • Githook将在提交时触发构建(在分支或任何其他方面 - 这只是一个配置问题)
  • CI将构建您的文件,然后将它们传递到测试阶段并发布

现在我正在我自己的项目上做Gitlab(作为业余爱好的一部分)一些网页.构建项目的Gitlab配置如下所示:

image: tetraweb/php

cache:
  untracked: true
  paths:
    - public_html/
    - node_modules/

before_script:
  - apt-get update

stages:
  - build
  - test
  - deploy

build_product:
  stage: build
  script:
    - npm run test

build_product:
  stage: build
  script:
    - npm run build

deploy_product:
  stage: deploy
  script:
    - npm run deploy
Run Code Online (Sandbox Code Playgroud)

当我合并到主分支时,发生以下事件:

  • CI运行build阶段
  • 如果构建成功,则test启动阶段
  • 如果test阶段正常,则最终deploy触发阶段

该脚本是要执行的unix命令列表.

您可以在配置中指定任何Docker镜像,因此实际上使用任何您想要的unix版本与一些(或不是)预安装的工具.

添加命令将构建推送到另一个分支是没有问题的.

有一个包deploy-to-git,它将伪像部署到所需的repo分支.

或者在这里(对于Travis CI)将工件发布到repo的配置:

特拉维斯 - 发布到混帐

(我自己用它)

然后,当然,你可以让CI运行:

npm publish .
Run Code Online (Sandbox Code Playgroud)

因为CI执行unix命令,所以它可以(至少有一堆CI提供者):

  • 发布标签(发布标签可能吗?)
  • 触发脚本以在所有README和所有地方更新项目版本
  • 如果所有阶段都成功,则向您发送通知

所以我做了什么:
我承诺,推动并让工具做我想做的一切.
与此同时,我做了其他更改,并在一到十分钟后通过邮件获得更新报告.

那里有很多CI提供者:

这里我附上我的另一个项目(.travis.yml)的另一个例子:

language: generic
install:
    - npm install
script:
    - chmod u+x ./utest.sh 
    - chmod u+x ./self_test/autodetection_cli/someprogram.sh
    - cd self_test && bash ../utest.sh --ttools stime --tno-spinner
Run Code Online (Sandbox Code Playgroud)

如果您设置CI来推送和发布您的软件包,您可以始终确保使用最新的代码版本而不必担心呃我现在也必须运行此命令...问题.

我建议你选择其中一个CI提供商.
最好的为您提供数百种能力!

当您习惯于自动进行发布,测试和构建阶段时,您将看到它如何有助于享受生活!
然后用自动脚本启动另一个项目只需复制配置!

摘要

在我看来,npm prepare脚本是一个选项.
您也可以尝试其他人.

每种描述的方法都有它的缺点,可以根据你想要实现的目的使用.
我只想提供一些替代方案,希望其中一些能适合您的问题!

我希望我帮助你一点点.
祝你今天愉快!


Roy*_*ker 6

假设 package.json 文件的 script 字段中有一个build脚本,是否可以将包配置为在这种情况下自动运行它?

是的。您需要做两件事:

  1. 确保您的系统使用npmyarn安装来自 GitHub 的软件包。如果此包是另一个包的依赖项,您可以使用 GitHub URL 代替 中的版本号package.json。否则,以下命令将起作用:

    npm install https://github.com/YourUser/your-package
    
    Run Code Online (Sandbox Code Playgroud)

    如果您要查找特定标签或分支,则可以/tags/v1.0.0在 URL 末尾添加或添加其他内容。

  2. 将以下内容添加到scripts您的模块中package.json

    "install": "npm run build"
    
    Run Code Online (Sandbox Code Playgroud)

install是包管理器在安装模块后执行的钩子。(preinstallpostinstall请参阅文档)。

文档: https: //docs.npmjs.com/misc/scripts