Dependencies hell
Tags: javascript, node, development
Published: 2022-03-20 15:18:27

---
title: Dependencies hell
published: true
description: A javascript dependencies are more complex and hard that you think. 
tags: #javascript #node #development
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yal1r5o1phq0213vqmxv.jpg
---

How does typical frontend project start? 

```jsx
git clone project

cd project

npm i
```

And we have received thousands of modules installed in the OS, megabytes (or gigabytes) of files. After installation we try to start a project using `npm start`, but we get some `node-gyp`, versions errors or vulnerabilities This walls of information, that we can't fix, are really frustrating. I want to talk about some of these problems.

## **What’s wrong with deps**

### Deps size is so big

Let’s see how much size popular project `Create React App` has:

![The Create React App empty project has around 300mbs of size](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9f4sjvpji8737wfhoaf.png)
 
It has 300mbs that does nothing. After template was created devs can install `mobx`, `axios`, `css-in-js` packages, components library, something like `lodash` or `rx.js`, some type definitions for typescript, etc. In result we have half of GB space of  empty project without actual code base.

I want to remind - we are in chip shortage, Apple asks ~200$ for 128GB. These gigabytes of packages, that we transfer back and forth, don’t just disappear — they are stored in our disks (and often this is global npm packages, that we can’t just delete as project dependencies), in DNS servers, in data centres. This is unbelievable how irresponsibly we develop software, without looking into future and software complexity.

## Deps doesn’t update theirs deps

How regularly devs update their package dependencies? During my practice, this doesn’t happen as often as necessary. Let’s look at `create-react-app` for example. It has `jest` as dependency with version `27.4.3`, when I wrote this article actual version was `27.5.1`. 
Jest has `micromatch` package with version `4.0.4` (that was actual version for `jest@27.4.3`). And `micromatch` has `minimatch` package with version `3.0.4`. But actual version is `5.0.1`, that solve, at least one major [security problem](https://github.com/isaacs/minimatch/issues/146).

And this is just five minutes research, `Create React App` has dozens of dependencies, which have dozens of dependencies, which have... One of them could be out of date or has vulnerability issues.

Deps control can be more hard with very popular projects. `Cypress` updates its version very often. Sometimes it happens twice a week. When I’ve started to use `Cypress` I updated it every two week, but then I just got tire to do this. But this was mistake - Cypress team, probably, fixed some major bugs, solved some vulnerabilities in this updates. But as developer in modern and big project, where you have many deps, you can’t hold dependencies actual every time. 

## Maybe you don’t need these deps

There are many instructions and StackOverflow answers that recommend: “Install `this` to solve your problem”. Package distribution systems (`npm`, `yarn`, `pnpm`) are very easy to use, they installed by default in some Unix-system, they installed with `Node.js`. And this ease doesn’t good for our industry.

Because complexity of IT is growing up from year to year, new folks learn only the tip of the iceberg (not all people, of course). Because the main goal of business is getting money, not creating good and robust software, we have no time to control every aspect of development. Open-source folks spend their own time to support projects.

And because of these points we don’t spend time to check package size, all dependencies (include dependency’s dependencies), vulnerabilities, but much more, we don’t think that this package is necessary. We install `Axios` instead of just using `fetch api`. We use `css-in-js` or `css modules` instead of using `BEM`. We could use just REST API, instead of `GraphQL`. And there is much more examples.

## What we can do

1. Prioritize robustness over development speed and “developer experience”.
    
    Ask yourself about package necessity, maybe there is standard library method for your problem, or you don’t need full module, just a part, that you can copy-paste to your project.
    
2. Check not only stars and popularity, but also maintenance, update regularity, communication with community
`CRA` doesn’t update about year, we don’t have any news from their team. This is red flag not to  use `CRA`. Actually, they released new version, but anyway, this was red flag :)
3. You can store node_modules in version control system
    
    That sound stupid, but this is easy way to maintain dependencies, to ask questions “why do I need this”. This care us from unexpected node_modules extending. 
    
4. Best practices are propaganda for juniors
    
    This topic can be disputed, but I think that the Patterns and other best practices, that puts into folks head to use it without thinking about necessity - are propaganda just as is. The Patterns are good, but we need to use it when we really meet a problem in code base. Sounds like I recommend to go to the Assembly and code using it, but no, I just recommend to think twice before doing something.
    
5. Solve actual problem, don’t solve future problem
    
    I have met so many times, when “architect” decided to use something like a store, argued that in future we could have a lot of data which we can share between modules and etc. And in this scenario we could use the react context and change it with store when we actually find a problem with data management. Another problem is technology FOMO - you need to use popular solutions, be in edge of technology. And there is much more examples when we solve problems that doesn’t exist. 
    

## Easy receipts using std

I want to show easy solutions of popular problems using standard library.

Often we have installed by default `Lodash` in our projects. `Lodash` give us some handy functions, some syntax sugar. One of the best function is `debounce`, that we use when we need to control user input.

![Receipt how to use lodash.debounce() from Lodash docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oc9z7snhydx33w3k104i.png)

What’s wrong, you can ask. [Source code](https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L10304) of function is unreadable. This is little function, but we install a whole `Lodash` for this. This is how debounce looks using plain JS:

```jsx
function debounce(func, timeout = 300){
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => { func.apply(this, args); }, timeout);
  };
}
// copy-paste from https://www.freecodecamp.org/news/javascript-debounce-example/
```

The difference is dozens of lines of code, is less maintainable, needs more code control.

We often use `css-in-js` or special setup of `webpack` to stop class intersection. Really simple solution is [BEM](https://en.bem.info/methodology/css/) — methodology of a class naming. We need to name every class like block_element-modification. Using React it looks like: `componentName_someWord`. This is easy. 

## Wrapping up

When I've written this article I never stood a goal to change your mind, but if you start to think more about dependencies - this would be cool.

I can recommend you to read or watch:

- [nikitonsky -](https://twitter.com/nikitonsky) [Software disenchantment](https://tonsky.me/blog/disenchantment/)
- Jonathan's Blow - [Collapse of Civs](https://www.youtube.com/watch?v=pW-SOdj4Kkk)

Thank you ❤️