Optional dependencies in npm?

I have a similar question to this, but not quite the same.

I would like for the user of my app to install it with whatever dependencies are needed for the way he would want to use it. So, for example, if they want to persist to MongoDB, then only Mongo-related libraries will be installed, but if they want to persist to Redis, then only Redis-related libraries will be installed. I don’t want to make them download and install libraries they won’t be using.

I know I can do that for development purposes with devDependencies, but this goes farther than that. As the answer in the question above says, this is more closely related to Python’s setuptools extras_require and Clojure’s leiningen profiles. Anything like that in npm? I really feel like devDependencies should be a dev profile of a more versatile way of specifying dependencies.

3

The codependency module may be what you’re looking for, or anything that does something similar to:

  • declare optional dependencies in package.json that aren’t automatically installed by npm install, say optionalPeerDependencies
  • a custom require-style function that knows about optionalPeerDependencies and does the right thing, including throwing/warning when nothing is found that fulfills a required class of modules (e.g. neither redis, nor mongo, nor mysql, etc. are installed).
  • document the expectation that consumers of this module install at least 1 of the optional peer modules

One variation would be if the module’s core functionality works without any optional dependencies (e.g. plugin pattern), no error/warning when nothing is found that fulfills a peer dependency.

Another variation is doing the list above while accounting for production versus development dependencies, i.e. an analog for dependencies and devDependencies.

Perhaps combined with an on-demand require such that optional modules are required lazily, e.g.:

exports = {
    Core : require('./core'),
    get redis(){ return require('./redis'); },
    get mongo(){ return require('./mongo'); }
}

2

If you want simple optional dependencies like plugins, e.g. if you install foo you will run it colorful but if not installed, you don’t have any problem and see it in gray, then you could use optionalDependecies in the package.json:

{
  "name": "watchit",
  "version": "1.2.3",
  "optionalDependencies": {
    "foo": "^2.0.0"
  }
}

And in the code:

try {
  var foo = require('foo')
  var fooVersion = require('foo/package.json').version
} catch (er) {
  foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
  foo = null
}

// .. then later in your program ..

if (foo) {
  foo.doFooThings()
}

Extracted from the package.json documentation.

1

What I do is configure an install script in my package.json, inside scripts, like this:

"install": "node ./my-tools/my-install.js",

It will run right after npm install finishes. I use it mostly for auto-generating a .env file with defaults.

The my-install.js script could run different commands, create files, ask for user input, so there you could say “Want Redis or Mongo?”:

const exec = require('child_process').exec;
const readline = require('readline');

// Insert "Ask question script" here
// using readline core module

if ( option == 'mongo' )
  exec('npm install mongoose');

if ( option == 'redis' )
  exec('npm install redis');

This is a very quick answer, check out readline for reading user input properly and child process for running commands and processing output, etc.

Also notice that the install script could be whatever you wish (python, bash, etc)

1

npm really wasn’t designed for this, as one of the hardest parts of dependency management is ensuring fast, reproducible builds that are easy and relatively failsafe. But I believe there is a use case, and there certainly was for me. So I wrote a package to do exactly what you are asking for.

My package is install-subset, and can be installed globally with npm install -g install-subset

https://www.npmjs.com/package/install-subset

First, you build whitelists and blacklists for named install subsets in your package.json like this:

"subsets": {
    "build": {
        "whitelist": [
            "babel-cli",
            "dotenv"
        ]
    },
    "test": {
        "blacklist": [
            "eslint",
            "lint-rules",
            "prettier"
        ]
    }
}

Then call it with, for example, install-subset test

This will temporarily rewrite your package.json to not install those packages blacklisted, then restore it, which depending on the packages can save a lot of time and bandwidth.

Also works with yarn, is open source and issues/PRs are welcome.

In many cases I use this on our ci server to lower build time, and on our latest React Native project, took our typical fresh developer install from 72 seconds to about 20 seconds.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật