DEV Community

Cover image for A different approach to frontend architecture

A different approach to frontend architecture

Will T. on April 12, 2021

This article aims to introduce a frontend architecture (for applications built with Vue, React, Svelte, etc.) that is easy to reason about and has ...
Collapse
 
jackmellis profile image
Jack

👍 really good article. I've been writing FE apps almost identical to this for a few years now and it's a great pattern to use. Bonus points if you use dependency injection to further decouple your layers!

Collapse
 
itswillt profile image
Will T. • Edited

Hi Jack, thanks for reading the article 😃.

In the example app, I'm already doing some simple manual dependency injections in the Application layer. In the frontend world, we still have to keep in mind code splitting & lazy loading, so dependency injection is a little bit different from what we do in the backend side I think.

Collapse
 
jackmellis profile image
Jack

Yes code splitting is a big issue for DI on the front end. In a node app, for example, you can just grep all of your dependencies when bootstrapping with very little cost. This is actually something I'm trying to work out right now 🤔

Thread Thread
 
itswillt profile image
Will T.

@jackmellis Please write an article about it if you ever figure it out 😍.

Collapse
 
tuanlc profile image
Lê Công Tuấn

Bonus points if you use dependency injection to further decouple your layers!

How do you use dependency injection on the FE side?

Collapse
 
itswillt profile image
Will T. • Edited

@tuanlc I guess you can check out Jack's article about it: dev.to/jackmellis/dependency-injec....

Collapse
 
michaelbailly profile image
MichaelBailly

Hello Huy, thank you for this awesome article ! It reminds me a lot Domain Driven Design, applied to frontend. Well done !

Collapse
 
itswillt profile image
Will T.

Thanks for dropping by. This architecture is indeed inspired by the CLEAN architecture, the Onion architecture and DDD, with a few tweaks to make it applicable to the frontend world.

Collapse
 
talyssonoc profile image
Talysson de Oliveira

What do you think of adding this to the post? Might be useful for people that are new to these concepts to understand the ideas didn't come outta nowhere. We lose a lot to context when we don't reference the canonical source of this kind of info.

Collapse
 
shaalanmarwan profile image
Shaalan Marwan

Hello Sir, is there any resource about how to apply this for react

Collapse
 
itswillt profile image
Will T.

@shaalanmarwan Perhaps in the future I'll write a detailed article about applying this architecture in a React application. But for now you can use the example repo where a React application is included.

Collapse
 
leob profile image
leob • Edited

Great article!

This is known as Hexagonal Architecture, right? DDD (Domain Driven Design) is another closely related concept. Problem is that most devs aren't familiar with it, and that for most small to medium apps it isn't really worth it. But for larger apps I'd say yes, it's worth looking at.

P.S. what I like about this approach is that you raise the abstraction level, and that you focus on the problem rather than the implementation, and you cut yourself loose from endless discussions about Redux, versus Context, versus whatever. What I like less about it is the added boilerplate, if you can get rid of that then you have a win win situation.

Collapse
 
itswillt profile image
Will T. • Edited

I don't know what this architecture should be called. Some say it's like Hexagonal Architecture, some say it's related to DDD. All I know is it got inspired by a lot of architectures 😁.

And yes, the trade-off of this architecture is it will add more boilerplates. So in the end it might not be worth it if you want to quickly build a small application.

Collapse
 
cfuehrmann profile image
Carsten Führmann

Very nice article! I'm a full stack developer used to Clean Architecture on the backend. Obviously, the frontend world has a lot of catching up to do in the architecture department. One specific thing that strikes me how is frontend state management (like Redux) should be passed into presentational components by dependency injection instead of the way it's currently done. It has to be said though that DI seems harder to do nicely in the JavaScript/TypeScript world. One reason why DI nicer in the backend is that backend languages allow DI containers to use injectees' static types (since those types are around even at runtime and can be accessed via reflection, unlike in TypeScript). So it seems a DI container in JavaScript or TypeScript will necessarily have a less convenient API,

Collapse
 
itswillt profile image
Will T.

One specific thing that strikes me how is frontend state management (like Redux) should be passed into presentational components by dependency injection instead of the way it's currently done.

I totally agree. I don't really like the idea of a state management tool being tightly coupled to UI components, but that is probably what library authors want though.

Collapse
 
joruch profile image
Joris

There are some good ways to do DI in the frontend nowadays, with BottleJS for example. Angular also heavily uses DI. Another reason why I don't get why people don't seem to talk about that more.

Collapse
 
cfuehrmann profile image
Carsten Führmann

I just glanced over the docu of BottleJS. It's interesting to see how the DI container API compensates for the language's lack of static types: When you register a service whose "constructor" has arguments, you have to list, during registration, the names of the registrations that should be passed for those arguments. For example, assume that Beer has three arguments:

var Beer = function(barley, hops, water) { /* A beer service, :yum: */ };
Enter fullscreen mode Exit fullscreen mode

Then, when we register Beer, we have to pass the names of the registrations for 'Barley', 'Hops', and 'Water' during registration:

bottle.service('Beer', Beer, 'Barley', 'Hops', 'Water');
Enter fullscreen mode Exit fullscreen mode

In a statically typed language, we wouldn't have to list 'Barley', 'Hops', and 'Water' during registration since they would be discovered via reflection from the typed arguments of the Beer's constructor. This is what I meant when I wrote DI containers are less convenient in languages without runtime types.

Be that as it may, BottleJS looks nice.

Collapse
 
ozzythegiant profile image
Oziel Perez

As far as I can understand this article, this seems to be the way Angular puts together it's apps. Everything seems to guide you to modularize not just features, but components themselves. I've always loved this about Angular, but unfortunately, its steep learning curve and verbosity makes it difficult to work with. If React had done this from the beginning and not encourage sloppy components with no direction as to how to organize apps, I would have chosen React a long time ago for my apps. Instead, I use Vue since it resembles Angular in terms on syntax but it's simplified; now I can just apply this architecture for large apps.

Collapse
 
kirkbushell profile image
Kirk Bushell

Good to read better architectural articles regarding frontend.

However, I would argue that your counter repository is part of the domain, not infrastructure. The code necessary to build out your counter, includes your counter repository. The infrastructure part consists of things like base repositories and their methods.etc.

The code you put in a repository is always an aspect of business knowledge and therefore, belongs in the domain.

Collapse
 
remshams profile image
Mathias Remshardt • Edited

Thank you for the concise article/summary.

We almost do/did everything like that but the facade for the store.
I always thought exchanging the store would never be required/an option. Turned out in one of our projects we had to do exactly that (replacing redux with plain angular services).
Even though we had no facades for the store in place, the separation of the domain and presenters into dedicated services/components already helps a lot. A huge part of the (old) redux based implementations is now replaced and it is/was possible without too much effort/pain.
So even if it seems like a lot of effort in the beginning these abstractions help a lot in the long run.

Collapse
 
itswillt profile image
Will T.

Yes, the benefits of this architecture will really shine the most in the long run even though you might find it a little bit verbose at first.

Collapse
 
tuanlc profile image
Lê Công Tuấn

Nice article!

Collapse
 
danielgomezrico profile image
Daniel Gomez

I understand your feeling, coming from android / iOS, where many projects follow this kind of architecture decisions vs going into frontend projects where it's difficult to find (or at least in my experience) projects that are not coupled with frameworks.

Thanks for sharing

Collapse
 
fabiocosta89 profile image
Fabio Costa

I like this architecture. It is simple and well divided.

Thanks for sharing.

Collapse
 
itswillt profile image
Will T.

Glad to hear you like it!

Collapse
 
robert_kovaluk_dc81f625a profile image
Robert Kovalčuk

Brilliant article, I was wondering what do you think about having a wrapper around i.e pinia stores, that with pinia stores, live in application layer, that accept adapters for data fetching and if you ever need to switch from pinia to whatever else, you just adjust the wrapper for a particular store to accept different type of state, or even make an interface as to what you expect the pinia or w/e store does. so you'd endup with something like this new UserStore(userAdapter, piniaInstance). for me, I created a base class for storage wrappers and I pass piniaInstances inside actual wrappers implementations, so they are coupled in that sense, however I can then in Vue create a Context object that contains all the necessary stores,auth etc. and inject it into components where necessary. This idea came to me when I was trying to listen to actions on pinia store and I didn't like the way you had to check for what action was called etc.

Collapse
 
newskys profile image
Kyusik Shin • Edited

Hi, Thank you for the great article.
I also agree that making week connection between modules is very important to long-term management.
by the way, recently Recoil is rising for state management, but It seems It's strongly connected with React and Hooks.
It makes me difficult to divide Infrastructure(state) layer from others.
have you any ideas about this architecture with Recoil?

Collapse
 
jamols09 profile image
jamols09

Hello this is really cool architecture, was wondering if you could share some core where it becomes more complex or have much more in it so I could learn more about this implementation

Collapse
 
itswillt profile image
Will T.

Hi, I intend to publish another article just for this. Please look forward to it.

Collapse
 
andygr1n1 profile image
Andrew • Edited

I've come to this article by recomendation and a very big thanks for this. I can say it is a really powerfull project management!

Collapse
 
topdev0401 profile image
Ryan Hollifield

Hi, Huy.

Great article!

But I have less experience in Vue.js so could you give me an overview about react?

How can react project be structured with this pattern?

Best.