Visualization of route navigation in a React app
Tags: react, network, router, graph
Published: 2021-09-19 23:00:59

This post describes how you can build your own visualization of the navigation inside a React web application. 

Such visualization can transform a complex user journey into a more easy to understand, interactive network graph.

## Context in my company
Tech stack: 
- react SPA
- react-router
- 30+ screens
- screens grouped in multiple bundles, loaded only when/if needed
- folder structure: `src/screens/<bundle>/<screen>`

## Problem
No single place to view all these routes, that would allow new developers to quickly understand:
- how the screens are split into bundles
- the available navigation pathways between these screens

The alternatives would have been to: 
- Look inside the collaborative design tool. However there was no representation of ALL the screens, but rather they were spread in multiple places, usually grouped by feature.
- Look inside the codebase, and follow the code. But this would be too tedious if you just want an overview of ALL the screens.


## Solution
This started as a side project that I played with in a few evenings, since I wasn't sure if the end result would look good, or if my colleagues would find it useful.

The idea was simple: run a script that would generate a network graph made of:
- nodes `[{ id, bundle }]` - screens, grouped by their bundle
- edges `[{ from, to }]` - directed arrows between the screens, indicating that the navigation between these 2 screens is possible.

These nodes and edges would be generated by looking through the codebase, with an algorithm described by the following pseudocode:
```
nodes = [];
edges = [];
bundles = findBundles(); // find all the src/screens/<bundle>
bundles.forEach(bundle => {
  screens = findScreens(); // find all the src/screens/bundle/<screen>
  screens.forEach(screen => {
    nodes.push({ id: screen, bundle  });
    paths = findDestinationPaths(); // regexp of PATH.[...] inside src/screens/bundle/screen
    paths.forEach(path => {
      edges.push({ from: screen, to: mapPathToScreen(path) });
  });
});
```

This script will output 2 files: `nodes.js` and `edges.js`. These files were added to `.gitignore`.

## Drawing the graph

I used vis.js network library ([link](https://visjs.github.io/vis-network/)) for drawing the network graph. 

This library comes with a few useful built-in features, out of which I used:
- left-to-right hierarchical layout
- color grouping, based on the bundle
- physics engine, using repulsion solver

_NOTE: I had to play around with some of the options, in order to find the ones that gave the best looking output._

## Running the script

I added a new script entry inside `package.json`, that does:
```
"view-network": "node scripts/network/extract.js && http-sever scripts/network/index.html
```

The `index.html` file will do a few things:
- import the generated `nodes.js` and `edges.js`
- import the drawing library
- draw the graph
- add extra UI features, such as a dropdown select menu, so that you can choose which bundles to view.

## Result

Here are 2 examples of graphs that can be generated:

_NOTE: I had to add some blur, so that I don't share confidential details._
![Example of network graph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0u0pwgn5s84rnlj2jg6o.png)

Another example, using a different layout:
![Another example of network graph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g6sgq16z5ov5kgbgrdhe.png)

## Conclusion

Sometimes your side-projects can turn out to be useful for your company.