Directory structure of NodeJS/ExpressJS/HandlebarsJS fullstack project

I know this type of questions are borderline for SO due to the subjectiveness of the answers, but is there any standard or best practise for the directory structure of NodeJS/ExpressJS/HandlebarsJS fullstack projects?

I have several of these projects and in each of them I still struggle on what should be the best approach:

Upvotes: 2

Views: 2566

Answers (1)

Sha'an
Sha'an

Reputation: 1266

As I see it you want explanation for a monorepo structure.

About the questions:

#1

Do you split by client/ and server/ ?

If the /server provides HTML and other static content to the /client in your full stack project, it makes more sense to do it differently. For example like this:

enter image description here

Think of the /src folder as the /server folder, and /public as /client.

#2

Do you have two node_modules/ directories and two respective package.json, one for client and other for server?

We are working in a monorepo and all our modules are nested. Due to our project structure, the front-end is not free anyway, so there is no need for a separate node_modules and package.json.

#3

If you split them, where do you put the templates/ and views/ used by the server to generate html code to the client?

We did not separate them. So all the workers goes to /src. Only the static part goes into /public.


What is the problem, and what is going on?

- Monorepo: For example we have a very busy social media application. Users upload millions of photos every day. In order to deliver this seamlessly, we need to scale up our servers. We chose horizontal scaling as the solution. But what is the problem? Problem: We wanted to scale up only the photo serving/uploading part, but due to our structure we had to scale everything at additional expense. So let's say there were no new members coming to our application, so that part was comfortable, but we scaled it up for no reason.

- Node/Express to serve static files: is just a bad idea. You should not use your application server (especially express) to serve static content like html, css, js and other libraries. The best way to serve them is via a content distribution netwrok (CDN). Or, serve then from your web server (nginx or apache).

- Unnecessary confusion: As you can see, everything is very complicated, and the modules are interconnected. Testing, sharing, working with the team are all very difficult. If we want to make a small change in our structure in the future, it may take a lot of effort.


How could it be better?

First you have to completely separate the frontend and the backend. You can use Express just as an API server. And you can use frameworks like React, VueJs, Angular for frontend. It doesn't matter, it can be plain JS/CSS/HTML too. And you can use servers like Nginx or Apache to serve them.

Try to adapt your projects to microservices architecture. Microservices architecture will both reduce complexity and provide convenience for you in any future structure changes. And it is easy to test. On this road, Docker can be a very good friend to you.

If you still want to stay in the monorepo architecture after everything, you can stay using the way I mentioned in About the questions section, there is no problem with it and in addition, it is useful to read this blog.


Extra

so in /public you just put static content? Why views/ go the /src if it is client related?

Think like there are three parts in our monorepo approach:

  1. static
  2. mix of static and dynamic
  3. dynamic.

1. Static: for example, when we say example.com/css/style.css it should serve us directly our css file (the same one we have locally). Or when we right click on any photo on the website and open image in a new tab, it should redirect you to an address like example.com/img/the_image.jpeg. Everything is ready and only needs to be served. This is what we call "static" here. And only those go to /public.

2. Mix of static and dynamic: Our code takes the data, fill in the necessary places, and presents the page filled with the data to the users. And all this happens in the /views folder. As you can see, there is a compile process here, the result is not ready at first. So it cannot be called "static".

If frontend and backend were separate. Our frontend javascript code would make a fetch call to our backend server, it would get the necessary data and fill on its own. And all this would happen on the browser independent from the server. (This was an example of pure client side rendering. Have a look SSR vs CSR )

(There are so many options and different methods for this job (using ejs, pug, handlebars or react, vue, angular) and if we go any further this will be an opinion-based answer. Or it's already an opinion-based, it will be even more)

3. Dynamic: Our regular backend code.

Upvotes: 9

Related Questions