Cache NPM dependencies on Jenkins pipeline
What I have done in my Jenkins pipeline for 3 different projects is using tar
instead of cp
and then npm install
instead of npm ci
, for each:
cd
to your projectnpm i
tar cvfz ${HOME}/your_project_node_modules.tar.gz node_modules
Then in the pipeline:
dir(your_project){ sh "tar xf ${HOME}/your_project_node_modules.tar.gz" sh "npm i"}
Of course it has the disadvantage that with time dependencies change and the install will take longer, but I've managed to reduce my disk space usage in the image by about 0.5GB and tar
is much faster then cp
(cp
~30 sec, tar
~5 sec)
Total install time went in my case from about 3 minutes to a matter of seconds.
Those parts of the Jenkinsfile will do the following:
On Branch master and develop, a fresh npm install is always executed.
On all other branches, the package.json will be md5 hashed and after the npm install the node_modules folder will be placed in the defined cache folder like:<CACHE_DIRECTORY>/<MD5_SUM_PACKAGE_JSON>/node_modules.
The next build can reuse the node_modules and doesn't have to download all the node_modules again.
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 '''}
}