The UpgradeJS Blog

Take Stock of Your Application With Static Code Analysis Tools

Whether you’re joining a team to work on an existing application, or just want to get a better idea of the status of the application you’ve been working on for a while, static analysis tools can help.

These tools can provide you with a better sense of the size and scope of your application, its architecture, and provide insight into areas of importance, high complexity, low test coverage or poor testability, and more.

Of course, these tools are no substitute for human review and team discussion, but they certainly can be used to expedite that process.

cloc (Count Lines of Code)

cloc opens a new window is a command-line tool that counts lines of code (LOC) in a given directory or file.

It can be used to get an idea of the size of a codebase and to track changes in code size over time. It will also identify what languages are used in each file and separate out blank lines, comments, and actual “source lines of code” (SLOC opens a new window ).

LOC statistics can give you an idea of how large your application is, as well as find large files or directories that could be an indicator of places that could use refactoring.

cloc is a very powerful tool that can do many things, including running a diff between directories or tarballs, etc, to tell you how the LOC stats differ.

Here is an example of running cloc on the Express opens a new window codebase:

$ npx cloc ./
     228 text files.
     214 unique files.
      15 files ignored. v 1.96  T=0.38 s (567.2 files/s, 75935.9 lines/s)
Language                      files          blank        comment           code
JavaScript                      153           4251           2497          16409
Markdown                         12            848              0           3764
YAML                              3             41             28            259
EJS                              19             27              0            214
JSON                              1              0              0             99
Handlebars                        3              5              0             71
CSS                               4              1              0             44
HTML                              7              2              0             42
make                              1              2              0             15
Bourne Again Shell                1              5              0             13
Text                             10              0              0             13
SUM:                            214           5182           2525          20943

We can see that the application is written almost entirely in JavaScript, with supporting documentation, configuration, scripts, and front-end templates and code.

At roughly 16.5K SLOC, it’s not as large of a code base as I might have expected. Let’s get a sense of how the code is structured.

Next I’d like to see what some of the largest JavaScript files are, so I will run:

$ npx cloc --include-lang=JavaScript --by-file ./
     228 text files.
     214 unique files.
      76 files ignored. v 1.96  T=0.41 s (369.1 files/s, 55859.6 lines/s)
File                               blank        comment           code
./test/res.sendFile.js               262              0           1150
./test/express.urlencoded.js         134              0            732
./test/express.static.js             122              6            686
./test/express.json.js               119              1            670
./test/app.router.js                 255            312            544

I’m truncating the full report as it’s pretty long. But I can quickly see that a large portion of the JavaScript code is in the test and examples. This seems good - we likely have a well-tested codebase with many examples of how to use it!

Now I’m interested in the actual application code, so I will filter out those two directories:

$ npx cloc --exclude-dir=test,examples --include-lang=Javascript --by-file ./
      33 text files.
      29 unique files.
      21 files ignored. v 1.96  T=0.02 s (835.4 files/s, 267381.1 lines/s)
File                                      blank        comment           code
./lib/response.js                           157            475            537
./lib/router/index.js                       124            160            389
./lib/application.js                        109            275            277
./lib/request.js                             72            287            166
./lib/utils.js                               51            126            126
./lib/router/route.js                        48             72            110
./lib/router/layer.js                        34             58             89
./lib/view.js                                38             68             76
./lib/express.js                             20             33             63
./lib/middleware/query.js                     9             16             22
./lib/middleware/init.js                      9             20             14
./benchmarks/middleware.js                    6              1             13
./index.js                                    2              7              2
SUM:                                        679           1598           1884

Wow! It looks like the whole Express framework is less than 2,000 lines of code. That’s pretty impressive for the amount of work this framework does in so many production applications.

Now we’ve got a pretty good sense of the size of this codebase, the languages used, and the amount of test and example code. That’s good to know, and we may be curious to open some of the largest files and see what they look like.

But there are more tools we can use to glean more “big picture” knowledge about the state of this application before we even dig into code and code quality analysis.

First, let’s see if the package.json declares what versions of Node it supports:

$ npm view ./ engines
{ node: '>= 0.10.0' }

We can see that it is quite backwards compatible, supporting all the way back to version 0.10.0 of Node. That’s great. I wonder how many of its dependencies support that far back.

With our open source tool opens a new window , depngn opens a new window we can check this!

depngn (Node Compatibility)

We can run depngn with this command:

$ npx depngn 0.10.0
|                                                                     |
|                        Node version: 0.10.0                         |
|                                                                     |
  package             │ compatible │ range
  accepts             │ true>= 0.6
  after               │ undefined  │ n/a
  array-flatten       │ undefined  │ n/a
  body-parser         │ true>= 0.8
  connect-redis       │ true*
  content-disposition │ true>= 0.6
  content-type        │ true>= 0.6
  cookie-parser       │ true>= 0.8.0
  cookie-session      │ true>= 0.10

It looks like most of the critical dependencies are quite backwards compatible. The few that failed were devDependencies like ESLint and mocha. So that’s encouraging.

npm audit (Known Security Issues)

We should also run npm audit to see if any dependencies have known vulnerabilities:

$ npm audit
# npm audit report

marked  <=4.0.9
Severity: high
Inefficient Regular Expression Complexity in marked -
Inefficient Regular Expression Complexity in marked -
fix available via `npm audit fix --force`
Will install marked@4.2.12, which is a breaking change

redis  2.6.0 - 3.1.0
Severity: high
Node-Redis potential exponential regex in monitor mode -
fix available via `npm audit fix --force`
Will install connect-redis@7.0.1, which is a breaking change
  connect-redis  3.4.0 - 4.0.1
  Depends on vulnerable versions of redis

3 high severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Hmm, looks like 3 packages have vulnerabilities, with the root causes being the marked and redis packages. But the recommended patched versions also contain breaking changes. This will likely require some exploration.

npm-check (Known Security Issues)

While we’re looking at dependencies’ versions, we can get an idea of how up-to-date they are. Are we using recent versions, or are we way behind?

npm-check opens a new window is a great tool for this.

npm-check CLI output

Seems like there are definitely some outdated packages in there, though this also pointed out that redis is only used in an example file, and not in the main codebase, so we can probably ignore that for now!


All these tools have given us a pretty good bird’s eye view of how large our application is, and how healthy its dependencies are.

But there is more we can find out! In subsequent posts we will take a look at how we can gain insight into the quality and complexity of the code, the architecture, and testability and coverage!

Did I miss any tools you love? Share this article in Reddit and we can start a discussion about it! ❤️