我们都知道用npm下载依赖项可能非常耗时,特别是当我们仅限于旧的npm版本时。
对我来说,作为一名开发人员,这不是什么大问题,因为我必须在我的本地开发机器上执行此操作,并且所有内容都与我项目文件夹中的node_modules缓存有关。但是现在我想把这个应用程序带到Jenns的CI环境中。
我意识到用npm下载依赖项花了很多时间。这是一个问题,因为:
npm下载项目文件夹中的依赖项,而不是Maven的/home/user/.m2
我必须在每次运行时清理Jenkins工作区文件夹,以避免git checkout出现问题。
我想要一个非常优雅的解决方案来缓存我的Jenkins奴隶上的npm依赖项,但到目前为止我只能想到:
从Jenkins工作区中删除除node_modules文件夹之外的所有文件夹。我不喜欢这个,因为如果我继续为我的项目创建分支,我可能会消耗大量的硬盘。每个分支都创建一个工作区。
在每次安装npm后执行cp ./node_modules /home/npm_cache
之类的操作,然后在代码结帐后执行cp /home/npm_cache ./node_modules
。
我觉得这些解决方案很糟糕。必须有更好的方法来做到这一点。
答案 0 :(得分:0)
我不会'知道node.js足以知道如何处理这一方面。但是可以在Linux机器上处理的一个简单方法就是在从git签出后立即将缓存目录符号链接到外部位置。每个代理机器都将维护自己的缓存,但无论解决方案如何,您都可能必须这样做。
我假设你已经调查过nodeJS插件,它无法做你想做的事情。
答案 1 :(得分:0)
NPM在~/.npm
答案 2 :(得分:0)
我在Jenkins管道中针对3个不同项目所做的工作是,对于每个项目,分别使用*(*(matrix + i) + j)
matrix[i][j]
而不是tar
,然后使用cp
而不是npm install
。
npm ci
到您的项目cd
npm i
然后在管道中:
tar cvfz ${HOME}/your_project_node_modules.tar.gz node_modules
当然,它的缺点是随着时间的变化,安装时间会更长,但是我设法将映像中的磁盘空间使用量减少了约0.5GB,dir(your_project){
sh "tar xf ${HOME}/your_project_node_modules.tar.gz"
sh "npm i"
}
比{ {1}}(tar
〜30秒,cp
〜5秒)
在我看来,总安装时间从大约3分钟缩短到几秒钟。
答案 3 :(得分:0)
我创建了这样的脚本来检查Jenkins中package.json的md5sum:
stage('NPM Build') {
steps {
sh '''
node -v && npm -v
'''
// rm -rf node_modules
sh '''
CACHE_FOLDER=${HOME}/.cache/md5
echo "EXECUTOR_NUMBER: ${EXECUTOR_NUMBER}"
MD5_FILE_NAME=package-json_${EXECUTOR_NUMBER}.md5sum
[ -d ${CACHE_FOLDER} ] || mkdir -p ${CACHE_FOLDER}
ls ${CACHE_FOLDER}
if [ -f ${CACHE_FOLDER}/${MD5_FILE_NAME} ];then
cp ${CACHE_FOLDER}/${MD5_FILE_NAME} ${MD5_FILE_NAME}
md5sum package.json
cat ${MD5_FILE_NAME}
md5sum -c ${MD5_FILE_NAME} || npm ci
else
echo "No md5sum backup"
npm ci
fi
echo "create new md5sum backup"
md5sum package.json
md5sum package.json > ${MD5_FILE_NAME}
cp ${MD5_FILE_NAME} ${CACHE_FOLDER}
'''
sh '''
npm run ngcc
'''
sh '''
npm run build
'''
}
}
答案 4 :(得分:0)
Jenkinsfile 的那些部分将执行以下操作:
在 Branch master 和 develop 上,总是执行全新的 npm install。
在所有其他分支上,package.json 将被 md5 散列,并且在 npm install 之后 node_modules 文件夹将放置在定义的缓存文件夹中,例如:
下一次构建可以重用 node_modules,而不必再次下载所有 node_modules。
parameters {
booleanParam(name: "CACHED_NODE_MODULES",
description: "Should node_modules be taken from cache?",
defaultValue: !'master'.equals(env.BRANCH_NAME) && !'develop'.equals(env.BRANCH_NAME))
}
...
stage('Build') {
steps {
cacheOrRestoreNodeModules()
echo "Performing npm build..."
sh 'npm install'
}
}
...
def cacheOrRestoreNodeModules() {
if (params.CACHED_NODE_MODULES) {
sh '''
MD5_SUM_PACKAGE_JSON=($(md5sum package.json))
CACHE_FOLDER=/home/jenkins/.cache/npm/${MD5_SUM_PACKAGE_JSON}
# check if folder exists and copy node_modules to current directory
if [ -d ${CACHE_FOLDER} ]; then
cp -r ${CACHE_FOLDER}/node_modules .
fi
npm install --no-audit
# if folder does not exists, create it and cache node_modules folder
if ! [ -d ${CACHE_FOLDER} ]; then
mkdir -p ${CACHE_FOLDER}
cp -r node_modules ${CACHE_FOLDER}/node_modules
fi
'''
}
}
答案 5 :(得分:0)
我选择在新的 docker 容器中运行每个构建,但仍然可以完成依赖项缓存。这就是我所做的:
node_modules
文件夹的文件中。这些 zip 都存储在主机(运行构建的节点)内的 /home/.cache/node_modules
文件夹中。所以,当启动 docker 容器时,它必须有一个像docker {
image dockerImage
args "... -v \"/home/.cache/node_modules:/home/.cache/node_modules\""
}
sh """#!/bin/bash -xe
function getNodeModulesListHash {
npm ls 2> /dev/null | md5sum | cut -d ' ' -f 1
}
frontendProjectHashZip="\$(echo "${project}" | md5sum | cut -d ' ' -f 1).tar"
[[ -f "/home/.cache/node_modules/\$frontendProjectHashZip" ]] && tar -xf "/home/.cache/node_modules/\$frontendProjectHashZip"
hashBeforeInstall="\$(getNodeModulesListHash)"
npm install
hashAfterInstall="\$(getNodeModulesListHash)"
if [[ \$hashBeforeInstall != \$hashAfterInstall ]]
then
tar -cf \$frontendProjectHashZip node_modules
rm -f "/home/.cache/node_modules/\$frontendProjectHashZip"
mv \$frontendProjectHashZip "/home/.cache/node_modules/\$frontendProjectHashZip"
fi
"""
getNodeModulesListHash
用于获取当前安装的软件包的哈希值。这个散列是在 npm install
之前和之后计算的,所以如果它们的值相同,那么我不需要用 node_modules
重新创建 zip 文件,但我可以保留我最初提取的那个。其余部分非常简单,逻辑与其他用户提出的非常相似。