Architecting Frontend Projects To Scale
Architecting Frontend Projects To Scale
Architecting Frontend Projects To Scale
dev.to/mmcshinsky/why-frontend-architecture-matters-1ldj
I, like any other web developers and engineers, prefer to make my work life as sane as
possible. Having structure not only keeps life a little more pleasant, but is critical to
scaling and even allows creativity to flourish! Having a clear structure and consistent
plan in my code keeps me performant, allows me to better plan for scaling, avoid
unnecessary refactoring code sessions, and understand the app hierarchy without
having to re-learn each component or service every time I need to change or upgrade
features.
Pretty much most developers who start out with most JavaScript frameworks use a
built-in CLI (command line interface) that another team has built for the said
framework in order to jumpstart the development process with minimal effort. Nothing
is inherently wrong with this approach and this saves developers a lot of time from the
first wave of configuration bugs. The next step after setup is to build out your code
structure. Everyone, without a doubt, has opinions on this and will strongly defend
their approach. I too have molded my own architecture that fits my projects as they
grow.
In this article we'll use the create-react-app starter structure as a base configuration that
anyone can start with when following along with this article and not get lost.
my-app
├── node_modules
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── serviceWorker.js
│ └── setupTests.js
├── .gitignore
├── package.json
├── README.md
└── yarn.lock
I have a decently strong opinion about the src and components folder. Do not use the
src or components folder for everything! This doesn't scale for larger applications and it
is super annoying to dig through giant flat lists of .js files when you want to find a
particular piece of code.
On the other hand, if you are going to be working on my project, lowercase file names is
the standard we'll be living by. It makes sense, easy to read, and pretty much all other
project types and frameworks use this approach. Also, hyphens between words is a
must even if it makes it a tad bit longer than you are normally comfortable looking at.
Most of your projects starting out are probably going to be 100% frontend based
working with an internal or external api or a separate data source that isn't bound
tightly to the frontend code. Our architecture may alter, for example, if we were to
structure our project with server side rending in mind. Let's take a birds eye view of
what we have in our new app's folder.
my-app
├── assets
│ ├── images
│ ├── scripts
│ └── styles
└── src
├── components
├── constants
├── models
├── routes
├── services
├── views
├── utilities
├── index.css
├── index.js
└── serviceWorker.js
index.js
In the provided example, index.js is used heavily to export multiple components or
represent the parent components (container) of a view or shared element.
Assets
Let's break assets down a bit and understand what is going on:
assets
├── images
├── scripts
└── vendors
└── styles
└── vendors
The assets folder within the src folder is usually located here to represent internal only
resources that should not be readily available to the public as a stand alone, linkable, or
downloadable resource. Pdfs, downloads, blog post images, etc... could be stored
instead in the public folder for mass distribution.
3/7
I'm not going to recommend a specific sub structure for images. I don't even have an
defined opinion except probably keeping images grouped by pages, features, layouts,
and specific use cases. Scripts will usually be third party libraries that don't have
natural integration (import/require) into your project and you are okay with them living
in the start or end of the body of your html document. The same goes for the styles
folder.
The reason there is a vendors folder is because it is much easier to handle internally
written files that live in the scripts and styles folders in the base folder while
external/third party libraries will live in the vendors folder. This will make it much
easier to reference visually for team members and even add associated overrides (if
your can't modify the main libraries file due to possible future updates), e.g.
bootstrap.min.css, bootstrap-overrides.min.css. Not ideal for some... but it is organized
and easy to refer to. Remember, scripts and styles are primarily meant for third party
libraries that will not be living within your main projects JavaScript documents and
stylesheets.
Components
We are going to keep the components folder because I still believe that it is important.
It's use should not be to hold your project but rather to hold components that will be
shared throughout your project. This includes: layouts, private, public, templates,
sidebar, header, etc... What ever you want that will be used more than once by multiple
modules or views.
components
├── buttons
├── forms
├── layouts
├── partials
├── private
│ ├── header
│ ├── sidebar
│ ├── card
│ └── modal
├── public
│ ├── header
│ ├── pricing-tables
│ └── footer
└── shared
Note that I like to divide components that whose sole purpose belongs to the customer
facing website or the user facing app by public and private. They could also be names
website and app or you could keep all components folders on the same level under
components. All that matters is giving a home or primary location to reusable
components for your project. When it comes to the plurality of folder names, I am still
undecided due to the high variable use cases of component naming.
4/7
Models and Services
Let's bundle these together. Using a MVVM approach as inspiration, models will hold
constructors that will mold incoming and outgoing server data into repeatable and
scalable objects. Services will hold the generalized and specialized functions that send
this data back and forth between the client and the server. Services will also hold state
based solutions like redux configurations or global context.
├── models
│ ├── client.js
│ ├── product.js
│ └── task.js
└── services
├── context
├── redux
└── api
├── clients.js
├── products.js
└── tasks.js
Constants
Anything that will be referenced globally in the app should be stored here. This can
include:
Note that this folder could be substituted for .env file(s) holding all information if it is
considered dynamic based on how your hosting is configured or company policy is
enforced.
Utilities
Utilities can be one or many files that define small utility functions that your app will
utilize. This may be things like specialized dates, formatters, or one use functions that
are needed often but don't belong to any one component or module in your project.
Putting routes into their own folder has been something newer for myself. Keeping
routes together and importing the views for the routes has made it easier to manage
how my more recent apps change as business requirements evolve. This is more of a
5/7
personal preference than an insisted pattern for others to use.
routes
├── components
│ ├── private.js
│ ├── public.js
│ └── index.js
├── index.js
views
├── private
│ ├── clients
│ ├── dashboard
│ ├── products
│ ├── tasks
│ └── index.js
├── public
│ ├── about
│ ├── auth
│ ├── home
│ └── index.js
└── shared
Once again, I like to make sense of how my projects is structured visually by separating
the public facing website and customer facing internal app. Each of these view
component folders is where the view for a route is defined.
client
├── index.js
├── client-redux.js
├── client.scss
├── client-styles.js
├── tests
├── components
│ ├── modal
│ └── // unique components for view
clients
├── clients-redux.js
├── clients.scss
├── clients-styles.js
├── index.js
├── tests
└── components
├── modal
├── list-item
| ├── list-item.scss
| ├── list-item-styles.js
| └── index.js
└── // unique components for view
This example contains a range of possible files you may be using in your project. We
also break out unique child components to the view that wouldn't make sense to have in
our shared component folder by keeping them inside the view's component folder. By
adopting a heavy view approach that contains just about everything related to the view,
6/7
we can utilize maintaining new and old code as it is implemented and deprecated. This
allows us to be lean and agile in our development cycle. We also avoid developer code
and pull request overlap as different developers work on different features.
Conclusion
With that, we have defined the general outline of a more scalable and maintainable
architecture. To an extent, this architecture is agnostic to your frontend libraries and is
meant to be modified to the needs of your team. As projects are living and ever
changing organisms, and I am fallible, please let me know if I am missing anything.
What are your favorite or preferred approaches to frontend structure? Let me know in
the comments below. I would love to hear from you!
If you want a starter version of this, a link has been provided here: React-Starter
7/7