Project and Folder Structure
Learning objectives
- You know some approaches for structuring the files of a web application project.
With tiny projects and when trying out things, the folder and file structure of the project is not too important. You can put all the functionality in a single file, and the application will work just fine. Similarly, you can store all the files in the same folder, if you choose to do so. However, as the project grows, it becomes more and more meaningful to structure the files in a logical way.
As an example, in the previous chapter, we worked on a project where the file structure was as follows.
tree --dirsfirst
.
├── templates
│ ├── login.eta
│ ├── main.eta
│ ├── registration.eta
│ ├── todo.eta
│ └── todos.eta
├── app.js
├── app-run.js
├── authController.js
├── mainController.js
├── middlewares.js
├── sessionService.js
├── todoController.js
├── todoService.js
└── userService.js
As we can observe, there are quite a few files, and the project is not even that large. In this chapter, we will discuss some approaches for structuring the files of a web application project.
Small- and medium-sized projects
A classic way to organize source code is to divide files into folders based on type. For a web application, this would mean having a separate folders for controllers, services, view templates, and so on. In such an approach, the app.js
and app-run.js
would be placed in the root folder of the application, while controllers etc would be placed in their own folders. In this case, the above application would be structured into folders as follows.
tree --dirsfirst
.
├── controllers
│ ├── authController.js
│ ├── mainController.js
│ └── todoController.js
├── services
│ ├── sessionService.js
│ ├── todoService.js
│ └── userService.js
├── middlewares
│ └── middlewares.js
├── templates
│ ├── login.eta
│ ├── main.eta
│ ├── registration.eta
│ ├── todo.eta
│ └── todos.eta
├── app.js
└── app-run.js
This structure already provide insight into the location of the files. As an example, if we would be looking for controller functionality, we'd be looking into the controllers
folder. Similarly, if we would be looking for a view template, we'd be looking into the templates
folder. In a similar fashion, adding new functionality would involve working with these folders -- as an example, if we'd want to add a new controller, we'd place it to the controllers
folder.
Larger projects
When applications grow, organizing files into folders based on type starts to slowly become cumbersome. One approach to organize a larger application is to divide the project into folders by feature, and to have an extra folder (or two) for common functionality such as middlewares. As an example, the above application could be structured also as follows, where functionality related to the same feature is placed into the same folder.
tree --dirsfirst
.
├── authentication
│ ├── authController.js
│ ├── sessionService.js
│ └── userService.js
├── main
│ └── mainController.js
├── middlewares
│ └── middlewares.js
├── templates
│ ├── login.eta
│ ├── main.eta
│ ├── registration.eta
│ ├── todo.eta
│ └── todos.eta
├── todos
│ ├── todoController.js
│ └── todoService.js
├── app.js
└── app-run.js
Depending on the size of the project and the features, one could also further divide the files by type within the feature folders, e.g.
├── authentication
| ├── controllers
| | └── ...
| ├── services
| | └── ...
| └── ...
├── main
| ├── ...
| └── ...
├── todos
| ├── controllers
| | └── ...
| ├── services
| | └── ...
| └── ...
├── middlewares
| └── ...
├── app.js
└── app-run.js
Conventions..
There is no single official approach for organizing files into folders. In practice, when working in teams, teams agree upon a shared convention that is followed (and revised over time).