My story after almost a year using Angular on daily basis, still having my ♥ in React ecosystem.
I’m a confirmed React evangelist, but currently, my main project at SportsBroker is based on Angular stack. I’ve been learning it for about 3 months, there is still a lot to do, but I must admit that changing base framework approach gave me some overall knowledge how to structure and develop my apps. Eventually, when I do side projects in React, I found myself adopting some of Angular solutions.
The worst structure approach I’ve ever seen in apps were naming project directories like “components/containers/styles” or in redux — “reducers/actions/types”. Each of folder contained components, but why the hell in component-based frameworks people are grouping by file type?
Of course, not every app is like that, and more common is to group component files in their folders. But how do you scale when you have hundreds of components? Thousands? How do you structure domain model and view containers (pages) related to dumb components?
Modules are the perfect answer to this problem. I’m not a fan how they are implemented in Angular (flattening of providers) and I prefer how it’s done in http://nestjs.com/ —the same concept but services are local by default.
Anyway, what Angular modules do:
- Group some (domain) functionality
- Divide app for smaller pieces that can be plugged on/off (if you do it right)
- Group lazy loading scope
- Declare module-specific components, pipes and directives
- Export public components, pipes, and directives
- Import other modules to have access to exported declarations and reexport imports
- Provide services for Dependency Injection
Example of modules in Angular could be “CheckoutModule” in e-commerce shop or “InputsModule” containing custom input components used in forms.
How did it help me with my React projects?
- I create
modulesdirectory in my
src, which is the parent for my domain pieces.
- Each module contains components specific to its scope.
- Each module contains its data model (I like to use Rematch), actions, effects, reducers, services.
- Additionally, each module could contain index.js file, reexporting all local files, so they can be accessed importing by other modules.
What is the benefit? It scales. New features in the app is easy to add developer doesn’t drown in hundreds of components without context.
2: Dependency Injection
Angular DI is great. It’s not a popular concept in frontend programming, but hopefully Angular makes it more accessible.
In the nutshell, each component or service can receive the instance of any (provided) service, created during bootstrapping the app.
By default services provided in modules are globally constructed singletons, but their scope can be restricted to components. Unfortunately, services in Angular can’t be scoped to a module.
One of the great advantages of having DI Container is decoupling all dependencies and bringing it to one layer. You register some class (or value) to injectionToken, so later accessing this token will resolve proper class.
This is a great way to bring your app configurations, services to components or replacing mock data services instead of data providers — until they implement the same public interface.
How do I benefit in React?
First, I write better, more testable code, by keeping more SRP and (manually) injecting smaller, more specific services to another.
Second, I experiment with libraries like Bottle.js, ideally, I’d like to achieve a similar effect as in Angular.
I’m quite poor at RXJS and reactive programming concepts, but the longer I use it, I find it more useful. It has a steep learning curve but brings a lot of benefits when you embrace it.
In Angular RXJS helps me writing data flow between services and view.
Even Redux as a concept of the immutable data stream is kind of observable.
Learning stream allows me to better understand functional programming, I am also interested in MobX because it’s based on streams as well.
Forms are one of the most crucial and one of the hardest to design pieces of frontend app. It has a lot of abstraction layers, data model, validation, server synchronization, UI state and how to synchronize it or how form controls should react with each other.
I’m not a fan of ngModel (2 way data binding) concept (however in Angular 2+ it’s ok), but Reactive Forms are really great. I learned how to design and structure my model, how to listen on form changes and assign validators.
It doesn’t mean I try to manually implement the similar solution in my non-angular apps. There is a great library which abstracts your form model called Formik. Also check out other projects by Jared Palmer (Backpack, After.js,razzle!).
5: Code style guide & standardization
While companies try to force their developers to keep some standards within their projects, Angular team has a higher goal — to standardize whole framework ecosystem. Of course, it’s hard to expect standards in React projects because it’s not a framework, you can use it any way you want to. On the other hand, Google makes use of its position, developing an opinionated framework with strict rules.
There is a style guide. I can’t say I agree with everything, but I try to follow the rules. Keeping conventions allow developers to understand a code they are used to see.
There are no “blessed” style guides for React/non-angular apps, but you can strictly force linters and other code style checkers to watch your projects. It’s great to work on and improve your eslint config file and share it within all company’s projects. What Angular tries to do globally, you can at least try to do it in your workplace.
- Static types save from *a lot* of problems. It doesn’t force you to be strict, but you can rely on some interfaces defined in your source.
- Libraries with typings are self-explaining and developer doesn’t have to check docs all the time.
- Code style easy to understand by Java, C# devs
- Really helps with refactoring
- … hundreds more