Setting up a good front-end architecture is a fundamental step to start developing a web app or a website. Good practices and coding conventions are essential, but what about the structure? How can we conceive a good architecture that is maintainable in time? But most of all, where should we start from?
When I started thinking about the problem, I realized I needed a couple of things:
- I wanted a multi-page project (a web app or website).
- I wanted my project to support different screen sizes and resolutions, in other words: I wanted it to be responsive.
- I wanted the final product to be maintainable.
- I wanted the final product to be performant.
- I wanted to reuse the same template for any future project.
The right tools
Nowadays we have a lot of cool tools that can help us in a modern front-end developing workflow. So, in facing points 1 and 2 I told myself I needed a breakpoint-based CSS architecture that could help me support different devices and desktop sizes. On the other hand, I also knew that such huge amount of CSS and files could be a bit messy (and so incompatible with point 3.), that’s why I decided to start using a CSS preprocessor (which was Sass with Compass in my case).
And what about the point 4? The answer was easy: I decided to use Gruntjs. Finally, what about point 5? Even in that case, the answer was there: Yeoman, the best solution in my opinion.
Organizing the workflow
We can choose to split all fundamental front-end components in macro-groups, such as the following:
- SCSS files
Can we we split them in smaller groups? Of course we can:
- common parts to every layout
- single layouts
- libraries (such as jquery, angularjs, gAnalytics and so on…)
- plugins (typically jquery plugins)
- controllers (I mean controllers such as angularjs controllers)
In a templating based architecture (for example using blade.php or jade with nodejs) we can also split views as follows:
- common parts to every view
- single views
But I am not discussing this case in this article, since I am assuming that there is only one view (an HTML file) for every page or layout in my project.
Starting from all of these preliminary considerations, this is how I decided to organize the architecture, here is my folder tree:
project \css \imgs \js \controllers pageOne.js pageTwo.js \libs angular.js jquery.js analytics.js \plugins jquery.tooltip.js textResize.js formValidation.js \views pageOne.js pageTwo.js \scss \framework _core.scss _forms.scss _input.scss _mixins.scss _variables.scss \layouts _all.scss _phablets.scss _tablets.scss _desktop.scss _desktop-large.scss _retina.scss \pageOne _all.scss _phablets.scss _tablets.scss _desktop.scss _desktop-large.scss _retina.scss \pageTwo _all.scss _phablets.scss _tablets.scss _desktop.scss _desktop-large.scss _retina.scss \libs _animate.scss _normalize.scss _reset.scss \plugins _jquery.tooltip.scss _jquery.fancyInput.scss
I decided to put all images files here:
.jpeg , wallpapers etc.
I decided to put all
.js files here, organized in subfolders as follows:
\ controllers (subfolder)
This is the folder for
angular controllers, each one with the same name of the corresponding view. For example, if your
home.html needs an angular controller, you should create a file like this:
\ libs (subfolder)
\ plugins (subfolder)
Plugin need dependencies to work, libraries don’t. So here is why I created a different folder:
\ views (subfolder)
I created this folder for all the presentational stuff. Each file has to have the same name of the corresponding view. For example if your
home.html needs some effects, stuff, and plugins initializazion, you should create a file like this:
project\js\views\home.js, that has its own
css (main folder)
This folder contains all of the generated
css from main the
scss files. For example
home.scss will generate the corresponding
home.css file in this folder.
\ libs (subfolder)
Even for the CSS files I am distinguishing between libraries and plugins. Here are some CSS library examples:
\ plugins (subfolder)
\ framework (subfolder)
I decided to put
scss files shared across all project pages in this directory
The framework subfolder will be organized as follows:
_variables.scss(project variables declaration – colors, spacings, etc.)
_mixins.scss(project mixin declaration – typography, clearfix, animations, etc.)
_forms.scss(custom form styling & reset)
_input.scss(custom input styling & reset)
\ layouts (subfolder)
And here is the responsive part. Files in this directory are organized in that way that they cover all screens resolutions, following a mobile first principle. So, you should start declaring your own styles using
_all.scss file. Rules declared in this file are valid for all screen sizes and all views. If you want your website to be adaptable, than just rewrite rules and declare them for any other screen resolution.
The folder is organized as follows:
tablets and small laptops (768up)
desktops with large screens (1204up)
retina displays exceptions (@2x)
These files will handle layout exceptions and are called by mediaqueries.
Please note: those files are shared across all views (HTML pages). That’s why you need to create a new folder under
scss\layouts to give a specific style to a specific page.
EXAMPLE – if you want to style a responsive home page and a responsive user-login page
scss\layoutsa new folder naming it with the same name of the views that you want to make adaptive (ex. home and userLogin) so:
Put the same files listed up above into these folders:
The final result
The final result is a Yeoman generator to scaffold a responsive multipages web app or website. I also decided to include some Grunt tasks for minification, obfuscation and Sass compiling. You can have a look at it here https://github.com/mcarella/wormhole, or download it directly from NPM: https://www.npmjs.org/package/generator-wormhole.
Where to go from here
I know this is not a universal solution, maybe in your case it looks like it includes some redundancy, and I know that it cannot suit all situations, but I think it is a good starting point. You can add as many grunt tasks as you want or organize your scss in a different way, making it lighter or fatter. No matter what your aim is, I usually advice people to roll their own architecture or framework tailored on their needs, paying particular attention to performance and maintainability without neglecting user experience.