In this short article, I will share with you my recent experience with documenting javascript code. I came to quite an interesting solution using JSDocs, which can be applied to almost any mid-size javascript application.
For the sneak peek of what I am talking about, you can check a related GitHub repository: LINK 2
So if you have an app where:
- Frontend
is written in React/Angular/Vue/Vanilla - API is written in Node.js
- And you also have a couple of (micro)services written in JavaScript…
…this article is for you.
I won’t tell you of how to install JSDoc in your project and what each JSDoc tag means – I will rather describe a high-level idea of setting up JSDoc to fully document the entire project.You can always visit my youtube channel and watch 2 episodes about JSDocs and better-docs.
But before we dive into details – let’s talk about: “why bother?
”What problem we are solving – aka why you might need documentation?
I’ve been involved in multiple IT projects for a decade now and there was always a need for some sort of documentation, for several reasons:
- To store and share ‘business’ information about the system, describe the commonly used terms etc.
- To describe the high-level architecture – which service is responsible for what.
- To describe low-level implementation details – what is the purpose of a given Class/Module, describe its interface and explain how to use it.
In this article, I’d like to tell you how I solved those problems in one of my recent projects. Everything will be grouped into 6 simple concepts.
6 Concepts
Concept no. 1: the root repository
Generally, ‘App Architecture’ and ‘Business Knowledge’ are terms which relate to all the services in the application. That is why I needed one place where I could put all the information regarding these 2 domains.
Since I used JSDocs I gathered all the code in one repo by using git submodules (https://git-scm.com/book/en/v2/Git-Tools-Submodules) – I will refer to it as the root repo.
To put it simply, git submodules allow you to link one repo with another.
This is the structure of the main folder of my root repository:
(git submodule) /fronted
(git submodule) /api
(git submodule) /microservice1
(git submodule) /microservice2
/infrastructure
/docs-src
/docs
package.json
readme.md etc
In /infrastructure I keep all the files related to docker and docker-compose.
/docs-src holds the files used by JSDoc, not necessarily related to code, like static files (images, screenshots) and tutorials (markdown).
/docs folder is the place where the actual documentation is stored.
I have to keep it in the repo because I deploy it on GitHub pages – take a look at deploying section.
OK – so this is how I handled multiple repositories. Next, I installed JSDoc3 in this root repo (that is why it has a package.json file)
Concept no. 2: JSDoc
Theory:
JSDoc is a markdown language used to describe the code written in javascript. It looks something like this:
/**
* Finds one Record in the Resource by its id
* @param {String} id uniq id of the Resource Record
* @return {Promise<BaseRecord>} record
* @abstract
*/
async findOne(id) {
//...
}
In the example above, we described the findOne function:
- what it actually does
- what arguments it takes
- what it returns
- and that it is an abstract method.
JSDoc3, on the other hand, is a tool which takes all the JSDoc comments and generates HTML documentation from them.
My approach:
Every repository (included as a submodule) has its own JSDoc comments. JSDoc3 can be fed with a configuration file where I defined that:
- all documentation should be generated to /docs folder
- JSDoc should parse all git submodules
- place where I put my tutorials will be /docs-src (read the next point)
…and a bunch of other options.
Concept no. 3: JSDoc Tutorials
JSDoc on its own creates a very good, low-level documentation for classes, modules etc. But it also allows you to add custom markdown files – they are called “tutorials”.
This is why I created /docs-src folder in the root repo – it is the place where I put markdown files for tutorials.
Tutorials are awesome when it comes to storing “Business Knowledge”. You can put there an overall architecture, installation instructions, relationship between services, database models etc.
Concept no. 4: Graphs with mermaid
The next thing I used were graphs created with Mermaid. Basically, you can add a graph to your JSDocs comments by using @mermaid tag (available via mermaid jsdoc plugin).
I also added some graphs inside tutorials with the following hack:
### Regular Markdown
Since markdown allows you to insert HTML, this is what you can do:
<div class="mermaid">
graph LR
A[BaseDatabase] -->|has many| B(BaseResource)
B --> |has many|C(BaseRecord)
B --> |has many|D(BaseProperty)
</div>
At the end of the file you also have to include mermaid:
<script src="https://cdn.rawgit.com/knsv/mermaid/7.0.0/dist/mermaid.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/knsv/mermaid/7.0.0/dist/mermaid.css">
<script>mermaid.initialize({ startOnLoad: true });</script>
Concept no. 5: A neat documentation
By default, JSDoc3 generates documentation which looks like this.
I tried to find a good theme which I could use (on JSDoc GitHub page there are a couple of links to different templates), but after all, I decided to ask one of our UI designers to create something super simple, yet very user-friendly.
Our Theme is called better-docs and can be found here: https://github.com/SoftwareBrothers/better-docs
And this is what the same documentation looks like:
Concept no. 6: Grouping things into a @category
When I set JSDoc to parse all the git submodules I ended up with a “not-so-well-organised” documentation (aka absolutely messy). So I decided to write a tiny JSDoc plugin which groups things into categories – it is included in the previously mentioned better-docs.
Long story short, by using it you can divide documentation into the categories on the sidebar. Again – take a look at https://softwarebrothers.github.io/admin-bro-dev/index.html – where Adapter, Decorators, Errors and PropertyTypes are categories.
And this was the last of the 6 concepts I’ve used. All of these things are not very innovative, but when combined together, they create a very powerful documentation toolset.
Deploying
There are a couple of options when it comes to deploying a JSDoc generated documentation. These are the most obvious ones:
- Publish it to AWS S3 bucket and host as a static page
- Generate it on a server and configure your Nginx/Apache to host it
- Use GitHub (or BitBucket) pages
Last time I used the third option – that’s why I created a /docs folder inside the root repository for storing documentation. You can configure GitHub to use it as a publishing source, it’s worth to check this out.
Once you’ve generated documentation in the source code, remember that you should push it from time to time. Think of your colleagues who get PullRequests with 20 files of updated HTML documentation – they will be frustrated… to say the least :).
Having a separate root repo for documentation solves this problem – commits with the code stay within the submodules, but PRs updating the generated documentation go to the root repo.
Summary
I have used this structure in 3 projects so far and it’s working quite well.
I’ve probably mentioned this already a couple of times, but you can see a working example here:
- Source code: https://github.com/SoftwareBrothers/admin-bro-dev
- The actual documentation: https://softwarebrothers.github.io/admin-bro-dev/
Hope you’ve found the article useful and some of the tips I’ve shared will make your dev life easier.