node.jsnpmpackage.jsonnpm-install

use npm with different configuration than package.json


I have a complex production environment driven by package.json.

The problem: I wish to install locally some additional packages, keep an eye on the list and versions of them.

Solution (how to get there): point npm to use another config file, excluded from git, which would keep my private dependencies. Use the file to add packages to local node_modules with npm install. So actually all I need is to change configuration context of npm.

I have no clue how to point npm to use a different config (something like gulp -gulpfile).

Update from comments The dev-dependencies is not the way to go. I use stuff 90% of other developers do not need to get installed in their node_modules (in fact I could break their environment in a strange way updating dev-dependencies in git-shared core project-wide package.json).


Solution

  • First of all, you should know that what you are trying to is not only weird, but also against a lot of good practices and patterns in NodeJS.

    Nevertheless, it's possible and if it's done right will almost never cause any trouble to you, or other developers in different platforms.

    You can use something a little inspired on the Meteor build flow. Let's break your project conceptually into two different parts:

    Project structure:

    - build.js (base build script)
    - package.json (base package)
    - internal/
      - package.template.json (project package template)
      - app.js (your actual project files)
      - [...]  (your actual project files)
    

    The starting point is create a package.json file to the Base, in the root of the project. This package will hold only the dependencies to build the package file of the Internal project. I strongly advise you to use something like Mozilla's Convict to ensure the configurations are done correctly using ENVs. The goal here is to write another package.json file at runtime.

    Let's also assume in the your environment there's an Environment Variable USE_WEIRD_MODULES="true". You can use this fact in the Base project to define which modules you are going to install using the build.js file. You can read it and edit in runtime. When it's ready, save it as internal/package.json. Then, run npm install inside the internal/ directory.


    build.js

    let pkg = require('./package.template.json');    
    
    if(process.env.USE_WEIRD_MODULES) {
    
        // Install your weird packages        
        pkg.dependencies.some_dev_package = '^v0.2.2';
        pkg.dependencies.another_dev_package = '^v0.2.2';
    
    
    }
    
    // Don't forget to save the package.json in the end
    fs.writeFileSync('./internal/package.json', JSON.stringify(pkg, null, 2), 'utf8');
    

    Don't forget to put the internal/package.json file in your repository ignore file (ex: gitignore).

    To minimize the impact of this brute changes in the project, you can define in the main package.json all the building routine in the postinstall script. It will allow a simple npm install in the root of the project handle all this steps internally.

    Something like this:

    package.json

    {
      [...]
      "scripts": {
        "postinstall": "node build.js && cd internal/ && npm install",
        "start": "node internal/app.js"
      }
      [...]
    }