鉴于项目的lib/
目录不应该被检入Git,因为它包含的文件是派生文件(来自构建过程)。从项目的github安装包时(例如在开发期间),lib/
目录将不存在,因此如果包package.json
{{1} }}字段指向(例如)main
,导入时无法编译包,因为这些文件在存储库中不存在,因此在安装到lib/index.js
的包中。这意味着需要构建软件包(就像在发布之前一样),只在本地这一次,以便node_modules
目录(或在构建过程中生成的任何其他文件)被添加到模块中。目录。
假设lib
文件的build
字段中有package.json
脚本,是否可以将程序包配置为在其所在的情况下自动运行仅从github安装?如果没有,从github安装时确保构建的最佳方法是什么?
现在有scripts
,prepublish
和prepublishOnly
生命周期挂钩,但没有人提供这个问题的答案,因为他们不允许任何方式区分来源安装。简而言之,是的,它们允许您构建安装,但它们不允许您仅从github构建安装。当人们从npm安装时,不仅没有理由强制构建,更重要的是,不会安装开发依赖项(例如prepare
,这对构建至关重要。)
我知道有一个策略可以解决这个问题:
babel
移除lib/
目录并将其签入。.gitignore
目录添加到lib/
并从git中删除dir。但这远非理想。我想这可以通过githook实现自动化。所以每一个你掌握项目的人都会建立并推动到一个单独的分支。
NPM的Github上有closed issue没有解决方案 - 只有很多人想要解决方案。从这个问题可以清楚地看出,使用.gitignore
不是答案。
我的用例是我正在开发一个在许多其他项目中使用的模块。我想使用最新版本的模块而不必在每次更新代码库时都向NPM推出一个版本 - 我宁愿在我准备好时推出更少的版本,但我仍然需要使用最新版本的lib在Github上。
注意:我也就此问题与NPM的支持联系,如果我收到回复,我会添加他们的回复。
答案 0 :(得分:15)
我没有正确理解这个问题。 以下是我写的东西,但有点偏离主题。 目前,如果您想从repo安装时仅运行build.js :
回购文件:
.gitignore
.npmignore
ThisIsNpmPackage
build.js
package.json
.gitginore
:
ThisIsNpmPackage
.npmignore
:
!ThisIsNpmPackage
在package.json中:
"scripts": {
"install": "( [ ! -f ./ThisIsNpmPackage ] && [ ! -f ./AlreadyInstalled ] && echo \"\" > ./AlreadyInstalled && npm install . && node ./build.js ) || echo \"SKIP: NON GIT SOURCE\""
}
我们的想法是在repo上提供文件ThisIsNpmPackage
,而不是在npm包中。(
安装钩子它只是一个bashy脚本来检查是否存在ThisIsNpmPackage
。如果是,那么我们执行npm install .
(这将确保我们devDependencies
。生成文件AlreadyInstalled
以防止无限循环
(npm install将以递归方式调用install hook)
发布时,我会git push
和npm publish
请注意,npm发布可以通过CI工具自动生成 - githooks
文件ThisIsNpmPackage
的这个小问题使得源检测可用。
调用npm install dumb-package
:
"跳过:非GIT来源"
执行npm install https://github.com/styczynski/dumb-package
将构建文件
我们在这里面临的主要问题是:
每次都必须npm publish ...
有时候修复一个小bug会有太大的痛苦,然后推送到repo并忘记在npm上发布。当我使用基于微服务的项目时,大约有5个独立子项目被分成模块,我发现问题,修复它并忘记在我所遇到的每个地方发布都非常烦人。
不想将lib
推入回购广告,因为它来源于
重新定位和合并更令人讨厌。
.gitgnore
哎呀,我知道这个问题,当你有一个你必须包含在repo中但却永远不会修改它们,或者有时候会删除的一些文件?那只是病了。
正如@Roy Tinker所说,安装时存在执行命令的能力 它可以通过npm钩子实现。
"install": "npm run build"
我们执行:
npm install https://github.com/<user>/<package>
修改强>
来自评论的OP问题:
但是对于每个从npm下载模块的人来说这都会安装吗?这是非常有问题的,因为从npm下载模块的任何人都不会安装dev依赖项。用于构建应用程序的库 - babel等将不会安装。
注意:但如果您需要特定版本的软件包(生产/开发),有或没有开发依赖项,您可以通过以下方式安装:
npm install --only=dev
--only = {prod [uction] | dev [elopment]}参数将导致只安装devDependencies或者只安装非devDependencies,无论NODE_ENV如何。
我认为更好的解决方案是使用:
npm install <git remote url>
然后在package.json中指定:
"scripts": {
"prepare": "npm run build"
}
如果正在安装的软件包包含一个prepare脚本,那么将安装其依赖项和devDependencies,并在打包和安装软件包之前运行prepare脚本。
示例:
npm install git+https://isaacs@github.com/npm/npm.git
在那里阅读npm文档:npm install
这是一种不好的做法,但很高兴知道。
有时(如 Electron framework 的情况,您需要根据不同的条件安装其他外部软件包或资源/模块)。
在这种情况下,使用代理的想法:
在您的情况下准备脚本就足够了,但我保留此选项,因为它有时可能会有所帮助。
我的想法是你编写一个模块并为它编写一个 install kook :
"scripts": {
"install": "<do the install>"
}
在这种情况下,你可以放在那里:
npm install . && npm run build
无论如何都安装所有devDependencies(如前所述准备案例),但它有点黑客攻击。
如果你想在那里做真正的黑客攻击:
"scripts": {
"install": "curl -L -J -O \"<some_url>\""
}
使用-nix命令curl
应该避免这种情况,但如果模块的每个平台都有巨大的二进制文件,并且您不想全部安装它们,那么它是一个选项。
就像 Electron 的情况一样,你已经编译了二进制文件(每个用于单独的平台)
因此,您希望人们install package
而不是install package-linux
或package-window
等。
因此,您在install
package.json
脚本
{
...
"scripts": {
"install": "node ./install_platform_dep.js"
}
}
然后在安装module
时,将执行install_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
这种以纯手工方式安装所有内容。
注意:此方法再次适用于依赖于平台的模块,如果您使用它,则可能会对您的代码产生设计问题。
我想到的是我真正用于日志时间的解决方案(使用CI服务自动构建)。
大多数CI服务&#39;主要目的是在推送到分支机构或使用repo执行其他操作时测试/构建/发布您的代码。
我们的想法是你提供设置文件(比如 travis.yml 或 .gitlab-ci.yml ),这些工具会处理剩下的工作。
如果确实不希望将lib包含到项目中,只需信任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
当我合并到主分支时,会发生以下事件:
build
阶段test
阶段test
阶段正常,则最终触发阶段deploy
脚本是要执行的unix命令列表。
您可以在配置中指定任何Docker镜像,因此实际上使用您想要的任何unix版本与一些(或不是)预安装的工具。
添加命令将构建推送到另一个分支是没有问题的。
有一个包deploy-to-git,可以将人工制品部署到所需的仓库分支。
或者在这里(对于Travis CI)将工件发布到repo的配置:
(我自己用它)
然后,当然,你可以让CI运行:
npm publish .
因为CI执行unix命令,所以它可以(至少有一堆CI提供者):
所以我做了什么:
我承诺,推动并让工具做我想做的一切
与此同时,我做了其他更改,并在一到十分钟后通过邮件获得更新报告。
那里有很多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
如果您设置CI以推送和发布您的软件包,您可以始终确保使用最新的代码版本,而无需担心呃我现在还必须运行此命令... 强>问题。
我建议您选择其中一个CI提供商 最好的为你提供数百种能力!
当您习惯于自动进行发布,测试和构建阶段时,您将看到它如何有助于享受生活! 然后用自动脚本启动另一个项目,只需复制配置!
在我看来, npm prepare script 是一个选项
您也可以尝试其他人
每种描述的方法都有它的缺点,可以根据你想要实现的目的使用。
我只想提供一些替代方案,希望其中一些能适合您的问题!
我希望我能帮助你一点 祝你有愉快的一天!
答案 1 :(得分:4)
prepare
是正确的方法如果您的存储库中包含源文件,但需要使用“构建”步骤来使用它,则prepare
会在所有情况下(从npm 4开始)完全满足您的要求。
prepare
:在打包和发布该软件包之前,在没有任何参数的本地npm install
上,以及在安装git依赖项时都运行。
您甚至可以将构建依赖项放入devDependencies
中,它们将在执行prepare
之前安装。
这里是an example个使用此方法的我的软件包。
.gitignore
的问题此选项有一个吸引很多人的问题。
准备依赖项时,Npm和Yarn将仅保留在files
的{{1}}部分列出的文件。
可能会看到files
defaults to all files being included并认为已完成。
容易遗漏的是package.json
主要是覆盖.npmignore
指令和,如果files
不存在,则{{1} }代替。
因此,如果您的构建文件像理智的人一样在.npmignore
中列出,请不要在.gitignore
中列出您的构建文件,也不要使用.gitignore
文件, files
将似乎损坏。
如果您将.npmignore
修复为仅包含已构建的文件或添加空的prepare
,则一切就绪。
答案 2 :(得分:3)
假设package.json文件的脚本字段中有
build
脚本,是否可以将包配置为在这种情况下自动运行?
是。您需要做两件事:
确保您的系统使用npm
或yarn
从GitHub安装软件包。如果此包是另一个包的依赖项,则可以使用GitHub URL代替package.json
中的版本号。否则,以下命令将起作用:
npm install https://github.com/YourUser/your-package
如果您在特定标记或分支之后,可以在网址末尾添加/tags/v1.0.0
或其他内容。
将以下内容添加到模块scripts
中的package.json
:
"install": "npm run build"
install
是程序包管理器在安装模块后执行的挂钩。 (preinstall
和postinstall
也 - 请参阅文档。)
答案 3 :(得分:2)
这是一个很好的问题。遗憾的是,没有公认的可靠解决方案,但以下方法似乎可行。
创建一个.buildme
标记文件,并提交到git。
在package.json
中:
"files": ["lib"],
"scripts": {
"build": "echo DO WHAT YOU NEED TO BUILD",
"prepack": "[ ! -f .buildme ] || npm run build",
"preinstall": "[ ! -f .buildme ] || npm run build"
},
这里是要注意的事情。
特殊的.buildme
标记文件应使用"files"
键或通过.npmignore
从npm软件包中排除。
prepack
钩子在您发布时运行(prepublishOnly
也可以工作,但是很高兴使用prepack
,npm pack
将产生正确的tarball)。
从npm安装时,preinstall
可以运行,但由于缺少.buildme
(由于[ ! -f .buildme ]
子句)而没有执行任何操作。
从github安装时,.buildme
确实存在。在npm6上,prepack
挂钩运行构建(并生成不包含.buildme
的程序包),而preinstall
不执行任何操作。在纱线1.12上,preinstall
进行构建。
如果您从github安装更新版本,preinstall
将再次运行,并重新构建。
注意:从github安装时,安装人员必须已经安装了软件包的devDependencies
才能使构建正常工作。 (此解决方案不会尝试自动安装devDependencies
。)
就是这样。它似乎可以与npm 6和纱线1.12的杂色组合一起使用。