Sunday, August 28, 2016

npm node module nesting and gulp copy issues

I was working on a project where the web application is running on a Node.js web server.  The CentOS 6.7 build server had Node 4.2.1 installed, and it had automatically come with npm 2.15.5.

I ran into a couple of issue when building / deploying the webapp package that was built on the build server:
  1. Webapp could not find certain node_modules during web server start.  The package with the same git tag would start flawlessly when built from a local windows machine!

    The windows machine was running node 5.1.0 that comes with npm 3.3.12 by default.  Since npm version 3.0.0 (https://github.com/npm/npm/releases/tag/v3.0.0), dependencies are installed "maximally flat", with no nesting.

    The culprit on the CentOS build machine was that it wasn't storing dependencies maximally flat, so during web server start, dependencies could not be located.  I upgraded npm to version 3.10.5 so all dependencies would be installed maximally flat (npm install npm@3.10.5 -g).

  2. All node_modules dependencies had to be packaged into the web application package, because the target environment did not have internet access to grab dependencies.  The gulp (CLI version 3.9.1) build script had a bug where not all hidden files under nested folders were being copied to the build dist folder appropriately in the CentOS environment.  The below four lines did not actually copy over ALL hidden files and folders:

    **/* - copy all folders, and their files
    **/.* - copy all folders, and their hidden files
    .**/* - copy all hidden folders, and their files
    .**/.* - copy all hidden folders, and their hidden files

    So I used gulp-exec command to do a Linux-only command line fix (I used npm to install gulp-exec version 2.1.2).  Below is the updated gulp task with the gulp-exec call:

    var exec = require('gulp-exec');
    
    //copy node_modules to dist folder
    //the four recursive copies under gulp.src does NOT recursively copy,
    //so an extra gulp-exec is added to make sure all node_modules are copied
    //to build/dist/node_modules.  Notice the "." at the end of the source node_modules,
    //this handles hidden files and folders.  
    //The exec is only expected to work on a Linux
    //server because the src/dest copy works fine in a Windows environment (a bug in gulp?)
    //so when erroring out in Windows, that is ok.
    gulp.task('copy:node_modules', function() {
      return gulp.src([
            'node_modules/**/*',
            'node_modules/**/.*',
            'node_modules/.**/*',
            'node_modules/.**/.*'
        ],{base:'.'})
        .pipe(gulp.dest(config.dist + '/node_modules/'))
        .pipe(exec('cp -R node_modules/. build/dist/node_modules/', 
             function(err, stdout, stderr) {
                      console.log(stdout);
                      console.log(stderr);
             }));
    });
    

After performing both steps above, the web application was built with all dependencies maximally flat and copied to the build dist folder appropriately.  The web server was able to start with the deployed webapp package.

Note:  I did briefly look into flatten-packages prior to upgrading npm version to >3.0.0, but ended up just upgrading npm since that should be kept up to date.

These articles were helpful:
https://docs.npmjs.com/getting-started/installing-node
https://github.com/npm/npm/releases/tag/v3.0.0
https://github.com/klaascuvelier/gulp-copy/issues/5

No comments:

Post a Comment

I appreciate your time in leaving a comment!