Hello everyone, just a little intro. I just started learning Node.js a few weeks ago. I came from a PHP background and I have been using it for around 2-3 years professionally.
I understand that Express.js offers freedom in structuring your application, but I need recommendations on how one usually structures their application (RESTful API) assuming that it will scale in the future.
My current directory structure is as follows:
- config
- controllers
- models
- routes
- api
- app.js
I mostly followed this repo as my inspiration. However, wearehive/project-guidelines stated that this structure is bad. I want to refactor my code to be able to follow it because personally, it makes much more sense if my project scales; my project will be seperated by features and not roles. But how do you even group these features?
I used Express.js because it's the most popular one and it's like everybody knows it or studied it first. I am open to other frameworks but will it be practical for a beginner like me to use, for instance, Restify or any other framework than starting out with Express.js?
Also, here are my dependencies so you can have an idea of the stack I'm using.
"dependencies": {
"bcrypt-nodejs": "0.0.3",
"dotenv": "^4.0.0",
"express": "^4.16.2",
"jsonwebtoken": "^8.1.0",
"mongoose": "^4.13.7",
"mongoose-unique-validator": "^1.0.6",
"nodemailer": "^4.4.1",
"passport": "^0.4.0",
"passport-jwt": "^3.0.1"
}
P.S.: Are there also recommendations on how you structure your app for versioning?
How do you usually structure a RESTful API?
Top comments (13)
Express is a good choice. It's simple and unopinionated, so you can add what you need when you need it and not get bogged down in someone else's ideal project structure.
"Someone else's ideal project structure" also describes those guidelines. That layout works for what they're doing; it may or may not work for you. Even in a bigger project, you may find it's easier to think "here are my controllers, where's the one for users?" vs "here's everything having to do with users, where's the controller?". I wouldn't be too concerned at this point. It's usually pretty obvious when something isn't working (technical or process), and then is a good time to poke around and see how other people have addressed the specific issue you're having. Source control lets you try things and roll back if they don't work so there's no reason not to experiment with various solutions when you have a problem.
If you do decide to group controllers and models together (routes should stay separate), you need to figure out what all you have. Draw up a data model, see what's in it, and divide them accordingly. Create a container directory to hold everything if you don't want it all right there in the project root. Using subdirectories or sub-subdirectories may be worthwhile to more accurately represent the model or it may be overkill; there's no way to tell without looking at it, and it's mostly a matter of taste.
Structuring the API is a different matter: there are rules to follow. If someone needs to see a list of users, there should be a GET route on
/users/
. If they can act on a specific user, there should be appropriate GET, PUT, POST, and DELETE routes on/users/:id
. I'm not sure if that's what you're asking though, or if you're more interested in the project layout.For versioning: structure doesn't really matter. Use
npm version
(or something like standard-version) to cut and tag releases. If your data model changes between releases, which it more than likely will, you'll need something to handle upgrading data. The key word to look for here is "migration", plus Node and MongoDB since there are many, many migration frameworks for everything and every database.Hi Dian! 🤗 Thank you very much for your answer!
For the first half of your response, you got what I meant by "structuring". I am more interested in the project layout than REST principles itself.
As for the versioning, what I meant was the
api.example.com/v1
vsapi.example.com/v2
how do you usually handle that? Is there a recommended project layout when preparing for this? Do you havemodels/v1/
,models/v2
or something?What you said makes so much sense. There is some kind of paradox in these good practices. So it's really a matter of taste and what my API is for then...
I have one last question. You mentioned that I could create a container folder for everything (this is what I want instead of leaving them to the project root), is there a naming standard for such folder? For example, the
dist
orbuild
folders have a naming convention for the final build of the app. I know it's a trifle, but I want to adapt™ to the javascript nomenclature as early as possible.Again, thank you for your response!
I've never had to worry about supporting multiple versions of a REST API at the same time, and I favor data access without models in JavaScript so that in particular is a bit of a moot point personally. I would try to avoid versioning models if at all possible simply because more code = more points of failure. There's no way around versioning routes because they have to do different things, but it should be possible to do those things with the same models even if you have to do a little fine-tuning here & there in the route code. If your schema is changing radically enough that that isn't practical, you probably have two different applications instead of two API versions. Unless you're tied into it for business reasons, such as "being Facebook", in which case all bets are off.
The conventional container folder name is "lib" in Node, although you'll occasionally see "src" instead.
All points taken. Thank you! 👏👏
Hi! endan a few months ago I created a little REST API with HapiJS, is not much different to express, here is the link to github repo if you wanna check it out github.com/lexmartinez/hapi-blog maybe that can help you.
Thank you for this! Example projects like these really help. I'll check it out!
You might want to look into Loopback or sails.js for building out REST APIs. They allow you to build things quickly. And they both use Express. See also Comparing Express, Restify, hapi and LoopBack for building RESTful APIs.
Having said that, it's probably good to first understand how Express works.
Good question. You may want to check out AdonisJS. If you have experience with Laravel, it will look very familiar :)
Hi Patrick! Yeah, oh it looks like Laravel indeed. I'll read about this too. Thank you so much!
I'd be interested to know what you think.
This is how I currently structure my Express API's:
Change bcrypt-nodejs for bcrypt. The first one is very old and without maintenance. :)
Oh. Thank you for pointing that out!