DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,673 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for πŸ’₯ Introducing Skott, the new Madge!
Antoine Coulon
Antoine Coulon

Posted on • Updated on

πŸ’₯ Introducing Skott, the new Madge!

Hello everyone, hope you're doing well!

Today I'm very pleased to share a fun project I have been working on for several months now: skott.

Skott

skott is a tool that generates a graph of dependencies from your Node.js projects (including both ES6 and CommonJS modules!) and helps you discover circular dependencies, cost imports, file sizes, unused imports/exports (work in progress), and many more πŸ’₯

Node.js builtin and/or npm third-party dependencies can also be configured to be added in the graph. The main goal is to reproduce the architecture of your Node.js application at the file level.

Installation and use

$ npm install skott
Enter fullscreen mode Exit fullscreen mode

skott provides an API to traverse the project graph, deeply search for circular dependencies, find parents or children for a given set of nodes, etc.

Here is a quick overview of the API:

import skott from "skott";

const { 
  getStructure, 
  findCircularDependencies, 
  findParentsOf, 
  findLeaves 
} = await skott({
  /**
   * The entrypoint of the project. Must be either a CommonJS or ES6 module.
   * For now, TypeScript files are not supported as entrypoints.
   */ 
  entrypoint: "dist/index.js",
  /**
   * Define the max depth of for circular dependencies search. This can be useful 
   * for performance purposes. This defaults to POSITIVE_INFINITY.
   */
  circularMaxDepth: 5,
  /**
   * This defines whether the base directory of the entrypoint must be included
   * in all the relatives file paths.
   * For the specified `dist/index.js` above, it would consider the root path
   * to be `./` consequently `dist/` would never appear in any file paths.
   */
  includeBaseDir: false
});
Enter fullscreen mode Exit fullscreen mode

skott can also be used through the CLI. Here is a quick preview of the graph generated for the fastify library, using the CLI:

Skott CLI on fastify

We can also decide to track more dependencies, for example the npm third-party dependencies (by providing the "--trackThirdPartyDependencies" option)

Skott CLI on fastify

Node.js builtin dependencies can also be tracked by providing the "--trackBuiltinDependencies" option.

File tree display

Different modes of display are available from the CLI, including file-tree which reconstructs a directory of files from the graph which is far more concise:

Skott CLI on fastify

Static image generation

In addition to various display modes from the CLI, Skott is also able to create static files reflecting your project graph, including .svg, .md. (using mermaid), and .png.

Here is an example creating a static file from skott itself:

$ skott dist/index.js --staticFile=svg
Enter fullscreen mode Exit fullscreen mode

Static graph image generation

For medium to big size projects, I'm trying to think about a solution to generate an human readable graph, maybe by grouping folders instead of displaying all files as nodes (which is way too much information). I let you try on webpack if you don't believe me 🫣

Circular dependencies

skott also helps finding out circular dependencies very efficiently in the project, you can even provide a max depth search to avoid deep searches that could be costly.

If you're not sure to see why circular dependencies can be problematic, I created a section Why you should care about circular dependencies and dead code in the root documentation of skott

Skott with Circular Dependencies

Some options can also be provided to the CLI to configure the exit code that will be used when circular dependencies are met (defaults to "1" meaning error exit).

Skott is fast

We can easily compare skott with madge because skott already covers most of the features madge exposes for a Node.js project.

I did some benchmarks about the computing time required to build a set of graphs from popular libraries for both skott and madge and here are the results:

Webpack (+560 files)

webpack is a static module bundler for modern JavaScript applications.

Webpack is probably one of the heaviest open-source Node.js project I know. So let's do a benchmark!

  • using skott takes 503ms

webpack benchmark using skott

  • using madge takes 2.5 seconds

webpack benchmark using madge

N.B: the difference of files between skott and madge is only because of .json files that are ignored by skott in the graph (as well as other files such as binaries).

Knex.js (+6O files)

knex.js A SQL query builder that is flexible, portable, and fun to use!

  • using skott takes 60ms
    knex benchmark using skott

  • using madge takes 450ms
    knex benchmark using madge

For building the entire graph of knex.js with even more metadata, skott is 7.5 times faster!

Fastify.js (30 files)

fastify.js is a fast and low overhead web framework, for Node.js

  • using skott takes 50ms

fastify benchmark using skott

  • using madge takes 350ms

fastify benchmark using madge

In this case, skott is 7 times faster than madge.

Stay tuned

Many more features will be implemented (skott does not yet have a major version released) to help you easily discover and demystify what's going on under the hood of your Node.js project! I'm also thinking about developing a Web Application that will help you visualize graphs and every metadata related to each file (number of imports, file size, unused imports, etc).

Sharing journey of building an open-source library

I'll also start a series about the journey of building skott, which notably includes:

Don't hesitate to bring stars ⭐️, issues, feedbacks directly on GitHub here as it will allow me to drive the project where it will bring the most value for each developer.

Thanks for reading this far, wish everyone a wonderful day β˜€οΈ

Top comments (14)

Collapse
 
ild0tt0re profile image
Angelo Annunziata • Edited on

WOW!! Finally a tool that will help us reduce technical debt and give us some metrics to take strategic decision on the codebase.
Thanks @antoinecoulon!

I will follow your interesting series about the journey of building skott.

Collapse
 
antoinecoulon profile image
Antoine Coulon Author

Thanks a lot for you feedback @ild0tt0re I appreciate it!

Tomorrow will be the first episode of the series dedicated to the journey, happy to know that you'll be following that =)

Looking forward to chat with you!

Collapse
 
frolovdev profile image
Andrey Frolov

Great one! What's the difference with dependency cruiser?

Collapse
 
antoinecoulon profile image
Antoine Coulon Author • Edited on

Thanks @frolovdev :) dependency-cruiser is a great tool, it's true that according to this introduction they look alike as they both enable graph visualization from JavaScript/TypeScript projects.

Nevertheless the main objective of Skott is not really to act only as a dependencies visualizer but instead its goal is to expose API primitives on top of the generated graph. This would allow the graph to be used to perform graph inspection (cyclic dependencies, unused nodes, dead code), graph diffing, but also creating incremental tasks orchestrator tools, etc.

Collapse
 
frolovdev profile image
Andrey Frolov

Thank you for the clarification, looks sick!

Collapse
 
darshan1212 profile image
Darshan Patel

Hey Antoine Coulon, This is so amazing! We are so grateful to you! It works like charm!

Collapse
 
antoinecoulon profile image
Antoine Coulon Author

Hey @darshan1212, thank you very much for your feedback, appreciate it a lot!
Feel free to open issues for either bugs or features if you have ideas in mind :)

Collapse
 
pdoy38 profile image
Patrick Doy

Looks like a promising tool!

Collapse
 
antoinecoulon profile image
Antoine Coulon Author

Thanks for the feedback @pdoy38!

Collapse
 
wadecodez profile image
Wade Zimmerman

Certainly a cool tool but what is the actual benefit of using something like this other than visualization? How can I use this to improve my project?

Collapse
 
antoinecoulon profile image
Antoine Coulon Author • Edited on

Thanks for the feedback @wadecodez :)
Visualization is just a support to draw the dependency graph of the project (you can start the project in headless mode), but the analysis aims to be wider than just for visualization purposes such as detecting cyclic imports, tracking unused imports/exports (not yet implemented), enforcing imports boundaries (not yet implemented) etc. The goal in the long run is not even the visualization as the primary purpose, but allowing a quick feedback about dead code, misconceptions, architecture smells for any project and for any programming language (only a JavaScript parser is implemented but Python, Go etc could be introspected the same way).

By the way, this is just the 0.2.* version so no a major release yet, I would be happy to hear any suggestion or feature that would be valuable for you.

EDIT:
Also another topic which is not covered up in this article is simply the fact of traversing and using the directed graphs generated by skott (find leaves, find deeply all parents/children of a given nodes, etc). For instance it could fundamentally be used by tools aiming to process incremental/affected tasks.

Collapse
 
wadecodez profile image
Wade Zimmerman

It would be cool if the tool could automatically remove cyclic dependencies and/or optimize imports.

Collapse
 
matiascarpintini profile image
Matias Carpintini

What’s that font? 😍

Collapse
 
antoinecoulon profile image
Antoine Coulon Author

@matiascarpintini Cascadia Code PL :)

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

β­οΈπŸŽ€ JavaScript Visualized: Promises & Async/Await

async await