16: Dependencies or Dev Dependencies, That is the Question
Understanding basic package management
11/14/20246 min read


I, a human coder, made a silly mistake. There was a time when I moved a package in our projectās package.json file from the dependencies section to the devDependencies section because it made sense to me then. How wrong I was!
Thankfully, it didnāt have a huge impact; it was for a developer tool and a new-to-us package. The issue resulting from the change was caught quickly. We rectified it with ease, and we all lived happily ever after.
However, I know Iām not the only one to fall into this trap. I thought it would be good to caution my former self and others who may not yet know the differences between a dependency and a dev dependency.
Here, weāll cover:
š Package & Module Definitions
š What is a Dependency?
š§š¾āš» What is a Dev Dependency?
Iāll share some examples and my story. Weāll keep it simple. š
š Package & Module Definitions
Letās quickly define a āpackageā and a āmoduleā in software development to ensure a common understanding.
A package is a file, directory, or resource set that can be publicly or privately shared. These packages can provide useful functions or tools for your project and are defined within a package.json file.
That package.json file is important! It holds all the details about your project, like authors, licensing, and scripts. It also houses your list of dependencies and devDependencies and the specific version numbers your project needs to work as intended.
One of the most common software registries for packages is npm. Iām sure youāve interacted with it at some point! My teams work a lot in Node, and npm also helps share and use Node modules similarly, loading something directly from a JavaScript or package.json file for use in your project.
In any case, npm uses your package.json file to determine which packages or modules you will need for your project. Remember that you will list a version number that npm will use to install the corresponding package. Take an extra moment to consider this for your project; failing to do so could result in feature compatibility issues, bugs, and instability.
Packages allow individuals, organizations, and companies to take advantage of existing solutions, saving time and resources. They also typically provide documentation to help users apply these solutions to their project needs. Keep in mind that the quality of documentation can vary greatly!
But using packages and modules is not all š rainbows and unicorns š¦.
When you add tooling like this, it needs ongoing maintenance - someone has to update it, fix bugs, and improve the documentation.
Hidden security risks can also exist, especially if the creator(s) no longer maintain it.
š What is a Dependency?
Dependencies are ultimately any package used in your project. Dependencies should be added to your package.json file's dependencies object to help your project function properly when deployed.
You might use these packages for development and testing, or they might be tools, libraries, frameworks, or other packages that improve an end userās experience.
The key thing to note is that these packages should be needed to run in production.
Here are a few packages we regularly use for Node API projects:
Consider these packages and why they ended up in the dependencies list.
If youāre unfamiliar with these packages, hereās the gist: Express is a Node framework commonly used to create a project server. Pino is a fast and lightweight logging library. Zod is a schema validation library we use to ensure that our āoutside dataā conforms to the TypeScript types we utilize in our codebase.
Now letās take a closer look at why each of these packages belongs in the dependencies section of the project.
Express is a bit obvious. How would an end user send over an API request without a server to connect with? We need a server on the production deployment for our users to reach our API. Easy enough!
What about Pino? As a logging library, we use this to send logs to our deployment cluster for local logs and to the observability platform to view all of our logs in one place. Yes, we need and use logs during development to ensure things are working as expected or failing as expected in some cases. However, arguably more importantly, we need our logs in our production deployment to tell whatās going wrong and why in the case of unexpected issues.
And Zod? Especially because we use TypeScript in my team projects, a more strictly typed language than vanilla JavaScript, we need to ensure the data we receive āfrom the outside worldā is what we expect. Regardless of language, a validation library lets us immediately stop invalid types in their tracks, keeping our app safer! As you might imagine from my earlier quote, āfrom the outside world,ā we expect these schema validations to be used in the production deployment. How else would we check that users are sending us what we expect?
Hopefully these examples provide a bit more context. To reiterate, when we need to use a package in the production deployment or if a tool is needed to interact with or validate user input, this is usually an indicator that your package needs to be located in the dependencies list.
Do you want more straight to your inbox?
Subscribe to receive occassional blog posts!
Your contact information will never be sold.
š§š¾āš» What is a Dev Dependency?
Now that weāve established what a dependency is, letās look at the other side of the equation - devDependencies. The devDependencies packages are specifically used for local development and testing.
In other words, if there is a package or module you only need to use during development, and your app doesnāt need it when deployed into the wild, that package should be added under the devDependencies object in your package.json file.
Here are a few packages we regularly use for Node API projects, along with the āoopsā package, which weāll talk about toward the end:
Letās start with the packages that belong here.
If youāre unfamiliar with these packages, here is the gist: C8 is a tool we use to check our test coverage natively in Node. Eslint is a popular linting utility tool to ensure your project follows the standards you put into place in your config file. This will typically follow your team or organizationās determined linting rules. TypeScript, which Iāve already mentioned, is a language that happens to be a superset (or added features on top of) of JavaScript.
C8 is purely for our internal purposes. Tests are frequently run locally, in development environments (where the app is actively being worked on), in staging deployments (which simulate the production environment), and in CI/CD pipelines. Tests in a production deployment serve no purpose and could negatively impact performance, especially as a project scales. Ultimately, C8 is for dev eyes only! š
Similarly, eslint is not something our users should know about. They wonāt be looking at our codebase, and itās unlikely that users would know enough about code - or our particular codebase or domain - to nitpick on our cohesive linting. Unless youāre working on an open-source project. But thatās a different story.
What about TypeScript? One could argue that you would need some level of language available to actually run the code, right? TypeScript doesnāt exist at runtime! Runtime code is essentially the executed code your users interact with. JavaScript files are created in the project's ābuildā or compile step, and Node can execute these files, so TypeScript is unnecessary in the dependencies section. Where TypeScript shines is its ability to write type-safe JavaScript code before it is compiled.
Letās talk about the 'oops' moment when I mistakenly moved a package that shouldāve been in dependencies to devDependencies.
My error came when I moved two BugSnag packages, like ā@bugsnag/jsā listed above, to the devDependencies section. We implemented BugSnag into a new project as a tool to monitor errors and track them down to squash them quickly! At first, it seemed like BugSnag should only be needed in devDependencies because it was a developer tool. Our users would not be interacting with it.
You may already see why that is an issue, but this made perfect sense in my initial mental model. When this change was deployed into our production code, we noticed an issue immediately.
We used BugSnag references in our handlers and application-level code that relied on this package and our production deployment couldnāt compile and build!
Iām grateful that the issue was quickly noticed and easy to fix. The team immediately reverted this to the dependencies section, and all was well. We implemented BugSnag to monitor errors and track them in real-time in the production environment, which is why it needed to be listed in dependencies. Without it in production, we couldn't run the app, nor reach the goal to catch and fix issues promptly.
Although dev tools are often only needed in the devDependencies section, consider whether it is actually used in production. In our case, BugSnag needed to be available in production because how else would we find and catch those bugs?
Of course, that makes sense. They say hindsight is 20/20.
I hope this cautionary tale is helpful for those who have just learned about dependencies and devDependencies or a good reminder for those who already know. Take an extra moment to think about your packages and where they belong!
š¤ Continued Reading:
If you want more details, I used these sources to help me refine my thoughts and phrasing!
npm - Specifying dependencies and devDependencies in a package.json file
DhiWise - Mastering Package Management: DevDependencies vs. Dependencies
A great, in-depth article. BONUS: They also discuss peerDependencies!
Stack Overflow - An old, but incredibly helpful question and answer
BONUS: peerDependencies mentioned here
Geeks for Geeks - Difference between dependencies, devDependencies and peerDependencies
BONUS: peerDependencies mentioned + a useful table!
Thanks so much for reading! āØ
Did I miss anything, or would you like to add anything?
Let me know!
I appreciate constructive feedback so we can all learn together. š
Connect
You can find Mindi Weik on these platforms:
mindi@wip-podcast.com
Ā© 2025. All rights reserved.
![[WIP] Podcast logo](https://assets.zyrosite.com/cdn-cgi/image/format=auto,w=375,fit=crop,q=95/Yan01MjyJEH16nVN/black-background-AMqDQ54p9xtwjbqg.png)