Welcome to Part II where we are going to speak about our first decoupling task, in this case, I chose the styles to be the first to be decoupled. We will do now do a more in-depth analysis of how to decide what is a common dependency and can be extracted to a package, and how to manage those dependencies.
You will see that there are other architecture decisions deeply connected. The first question you will want to ask yourself is...
Let's propose a teaser as an example. What will the markup of a teaser look like? Traditionally a teaser displays an image, a title, and a subtitle, a description, and a link or button. It may also show tags, categories, social media likes, etc.
Let's propose a simple one with an image, a title and a button. If you were going to put it together, it would look something like this.
Disclaimer: This is a very simplified markup output. It's likely your components will include a lot of dynamic and configurable attributes.
Now if you want to style it, your CSS (we will be writing scss in these articles), would look something like this.
You can see it here too: https://codepen.io/frontendnat/pen/zYvYoWX
But look at it, and think about it. Particularly when you're working with a strict design system or guidelines, (that's always the case in enterprise applications, but also products and even smaller apps developed by professionals), it is likely that all buttons in your app, will look the same. At least you will have a set of them, all looking alike.
Your headlines will also respond to certain UI/UX rules, in order to organize content efficiently and help with accessibility optimization.
Your images will all be responsive in the same way, so they will probably have global constraints all alike.
If you style your button, your image, and your headlines every time in each of the components stylesheets, you will end up with a lot of code repetition! So it won't matter if you lazyload each component independently...you will have a lot of code over and over
That is extremely unnecessary! Let alone hard to maintain: let's suppose the design changes, you will have to change definitions multiple times, once per component!
It will also be a lot more difficult to reuse code on a different platform or even tenant. The number of changes to be made would make it impracticable.
Now you may say, ok, you can delegate those styles to helper classes. That's correct. You may. But then you will have a lot of non-corresponding classes in the markup of your component. And a lot of backend/template logic, to make those classes dynamic.
When we're talking of multi-tenant architectures. Where components markup is shared by different tenants, this pattern is very difficult to maintain.
I propose you explore, a different solution...
If you think about it, the teaser is not a feature in itself. It's more like a container. The actual features are the members that compose it. In our example, the image, the title, and the button.
So now you have identified components you may be using over and over, and decided to create composites out of them.
Now you can reuse your button anywhere you need it by importing its markup and configurations, and that means you can also extract and reuse its common styles.
Let's elaborate a bit more on why this solution may not be so efficient.
First of all, if you put together a set of helper classes, *you will need to import them to be concatenated with the output you ship to the client. All of it. *
In a dynamic environment like an enterprise CMS, for example, it is unlikely you need all those classes on every page since pages have different sets of components. But you will still be sending all that CSS to the user, which plays against your site's performance and the user's data quota.
What you need to do is transform common definitions into abstracts!
Read the next part, to learn more about abstracts, how you write them, and how you import them!