A Reflection: Building a GraphQL API with Nest.js
The GraphQL Playground endpoint for my Nest.js/GraphQL API
During my investment time, I explored Nest.js as a framework for Node/TypeScript development. In order to compare it to our traditional stack, I decided to build a proof of concept (POC). I wrote this piece in order to reflect on what I built, and share my thoughts with the community.
What I built
I built a GraphQL API using Nest.js, which connects to a Postgres database with TypeORM. I also added authentication using OneGraph.
How it works
It works by serving a GraphQL API (Apollo Sever under the hood), which talks to a Postgres database. GraphiQL is served via a static HTML page to the client on the /playground
route. Mutations are protected by GitHub authentication using OneGraph. In order to execute any mutations, you must login with GitHub. Queries are all unprotected. On top of that, only members of the echobind
organization on GitHub are authorized to execute any mutations.
Live demo: https://jsjoeio-nest-graphql.herokuapp.com/playground
Note: the app is running on Heroku so it may take 2 mins to start up
How this compares to our recent client project
Our most recent client project used the following tech stack:
- Apollo Server
- GraphQL
- Node.js
- TypeScript
- TypeORM
- Postgres
And this is how data flowed:
Data flow in our regular GraphQL setup
Alternatively in the POC, I used this stack:
- Nest.js (uses Apollo Server)
- GraphQL
- TypeScript
- TypeORM
- Postgres
- OneGraph
In the POC, here’s how data flowed:
Data flow in the GraphQL with Nest.js setup
These look almost identical and that’s because they are, with the exception of the “Service” piece in the Nest implementation.
The main difference actually lies in the code structure and organization of files. In our client project, we used categories to organize things.
Whereas in the POC, things were organized by module. The module being the actual thing itself, this might be something like ‘user’ or ‘job’ in the client project.
I don’t believe this type of folder structure is required for Nest, but it’s definitely encouraged via their CLI file generator. You can see another example of this in their sample/graphql-apollo repo.
One thing I liked about this approach was that it felt more structured. I knew exactly what files I needed when I set up my module. Every file related to that module was prefixed with the module’s name, which in this case was “employee”.
Overall, I enjoyed the patterns, structure and organization encouraged by Nest. Even if you don’t use it, it may provide a new perspective on file structure that’s worth exploring.
Pros & Cons
Looking at both approaches, I made a quick list of pros and cons of using Nest.js compared to our other approach.
Pros
nest-cli
gives you generators out of the box (similar to hygen)- Supports TypeScript out of the box
- Solid documentation
- Framework encourages specific patterns
- Helpful testing utils
- Active development (4 patch releases in last month)
- Feels stable, sturdy → think it would scale well
- Allows single API to support both GraphQL & REST endpoints
Cons
- Heavy use of decorators makes some things feel like “magic”
- Feels similar to Redux development
- To do one thing, you need an action, reducer, and an action creator
- With nest, similar type of thing (module, service, potentially more)
Conclusion
Nest.js is an exciting new framework for back-end development. It supports TypeScript out of the box and can provide a quick way to develop a GraphQL API. The opinionated file/folder structure is excellent because it’s one less thing to think about from a developer’s perspective. I plan to explore Nest.js further in the future and keep it in my toolbox for future client projects.