errata
errata

Reputation: 6031

How to calculate the percentage of npm dependency usage in NodeJS project?

Is there a way to calculate how many lines of code were actually triggered and used from an npm dependency defined in my project (package.json), regardless of how the dependency is imported later in project (the whole library or just a part of it)?

What I would like to achieve is to see if a dependency is worth of installing or not in some fairly big project I have, for example, if there's only 1% of library used, then it's maybe better to just write those few lines of code myself than rely on the whole library and its dependencies.

Upvotes: 2

Views: 802

Answers (1)

mihai
mihai

Reputation: 38543

I've found a solution that involves some minor hacks, but works pretty well.

The idea is to use a code coverage tool and use it to inspect node_modules as well, in addition to your code.

nyc seems to be a popular code coverage module, so I went ahead and installed it: npm install -g nyc

I created a small example using 2 dependencies:

index.js

const mkdirp = require('mkdirp')
const ejs = require('ejs')

ejs.render('test');
mkdirp('.');

Running nyc node index.js only gives the coverage for index.js, which is not what we want:

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|

It seems like nyc doesn't descend into node_modules and there is no way to configure it to do so. This issue was raised in their Github repository as well: Include certain node modules #833
Fortunately, someone gave a workaround: manually modify test-exclude, a dependency for nyc.

This is how I managed to get it working:

  • Find the global installation folder for nyc (mine is: C:\Users\mihai\AppData\Roaming\npm\node_modules\nyc)

  • Within this folder, go to node_modules\test-exclude and edit index.js

  • Find this array:

    exportFunc.defaultExclude = [
      ...
      '**/node_modules/**'
    ]
    

    Modify '**/node_modules/**' to '**/nyc/node_modules/**'

  • Comment out these lines:

      if (this.exclude.indexOf('**/node_modules/**') === -1) {
         this.exclude.push('**/node_modules/**')
      }
    

Now everything is set, and we can run nyc node index.js again:

----------------------------|----------|----------|----------|----------|-------------------|
File                        |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------------------|----------|----------|----------|----------|-------------------|
All files                   |    42.75 |    29.34 |    40.48 |    43.03 |                   |
 myapp                      |      100 |      100 |      100 |      100 |                   |
  index.js                  |      100 |      100 |      100 |      100 |                   |
 myapp/node_modules/ejs/lib |    42.37 |     28.5 |    36.11 |    42.37 |                   |
  ejs.js                    |     42.2 |    29.32 |    44.44 |     42.2 |... 06,910,911,912 |
  utils.js                  |    44.44 |    11.11 |    11.11 |    44.44 |... 42,156,159,162 |
 myapp/node_modules/mkdirp  |    41.07 |    33.33 |    66.67 |    43.14 |                   |
  index.js                  |    41.07 |    33.33 |    66.67 |    43.14 |... 87,90,92,93,97 |
----------------------------|----------|----------|----------|----------|-------------------|

Note the coverage for ejs.js and mkdirp, showing Statements, Branches, Functions and Lines.

Upvotes: 3

Related Questions