Skip to content

dependencies vs devDependencies

Posted on:November 7, 2019

It’s probably the most famous dilemma after Chicken or the egg, should I install this dependency in dependencies or in devDependencies?

Let’s see what npm and yarn say about it:

NPM

dependencies: Packages required by your application in production. devDependencies: Packages that are only needed for local development and testing.

(https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file)

YARN

dependencies: These are your normal dependencies, or rather ones that you need when running your code (e.g. React or ImmutableJS). devDependencies: These are your development dependencies. Dependencies that you need at some point in the development workflow but not while running your code (e.g. Babel or Flow).

(https://yarnpkg.com/en/docs/dependency-types#toc-dependencies)

They are both speaking about dependencies needed by running your code but there isn’t any mention of building it. Even though yarn, in the example, is suggesting that modules like babel and for correlations @types should be installed as devDependencies. So what to do?

I decided to give a look at two of the one-line installers I have used lately the uber-famous create-react-app and the newborn create-next-app. They both install all the dependencies as normal ones.

    "dependencies": {
      "@types/jest": "24.0.22",
      "@types/node": "12.12.6",
      "@types/react": "16.9.11",
      "@types/react-dom": "16.9.4",
      "react": "^16.11.0",
      "react-dom": "^16.11.0",
      "react-scripts": "3.2.0",
      "typescript": "3.7.2"
    },

package.json created by create-react-app So create-react-app, which is maintained by Facebook (the same maintainer of yarn), is installing all the @types (using yarn) not according to what is suggested by yarn itself.

Despite what those two giants are doing there is another thing to keep in consideration, the size of the files. If you have built lambda functions before you most likely clashed with this, you want to keep your code shipped to your lambda as tiny as possible, so you don’t want to send along all the @types or all the babel plugins. You will most likely install all your dependencies at build time and then deploy a small package with only the dependencies needed by the application to run. Or you can even ship the built package without the dependencies and install them in the server (probably even caching them) with the handy --production (or --prod or -p) flag. npm install --production or yarn --production is going to install only the packages inside dependencies, excluding the one in devDependencies.

There is another scenario though, you want to spin up your application without caring about all the test/lint dependencies. In this case,  npm install --production will install only the modules needed to start your application, and yes, unfortunately, @types are part of those. It could be handy to save a few seconds, especially if you are installing heavy packages (yes, cypress I am looking at you).

Given both of the scenarios, I think the first approach is the most valid one, the second is covering just a niche and, if you are not installing a lot of different applications from scratch all the time, I don’t really see any long-term benefit.

TL;DR

Can you run your application without this dependency? Yes, devDependencies, No, dependencies.