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
.