Implementing a Frontend with Micro-Components

Jamie Gross
ITNEXT
Published in
6 min readSep 8, 2019

--

Before you you give me this look…

The micro-services concept has had quite a lot of buzz lately and is picking up steam with enterprise companies such as Netflix. It’s the idea of splitting your backend services into smaller pieces which are mostly independent of each other. This pattern is usually compared against monolithic applications which have ruled the backend for a long time. I would argue a micro-component architecture has the same goals as a micro-service architecture and many of the same benefits, but implemented slightly different.

So what do I mean when I say micro-components? I would describe it as a frontend architected such that a bigger application is broken into many small components who are independent and unaware of other components in an application. If you have done any SPA development (Angular, React, Vue, etc) this pattern will sound familiar to the “parent to child” component communication pattern.

I would describe it as a frontend architected such that a bigger application is broken into many small components who are independent and unaware of other components in an application.

Overview

Let me explain the pros of implementing a micro-component architecture before I give an overview of how it’s accomplished, or at least, how I did it.

  • Each component is owned by a single developer
  • Each component is designed to function independently, unaware of who the parent is (could be an application or another component)
  • An application can be updated to use new versions of the components without code changes (assuming input and output communication doesn’t change)

The last point has been the most important for me. My team is able to develop components in their own playground, publish the code, and rebuild the parent application within our CI/CD to reflect the changes.

High Level

My particular example, which I will explain below, uses Vue.js. You could, however, accomplish the same with Angular or React. Vue.js has a very simple process of creating “libraries” which is the foundation of how the components for the micro-component are generated and then used. On top of that, there was a non-functional requirement to use Vue.js for our particular project.

Here is what a normal monolithic application looks like.

There is one application with no components, all inside a single code base. Now here is the micro-component pattern.

You can see above that there are a lot more lines. The purple lines represent a connection to a published NPM package. The NPM registry needs to be private of course, unless you’re wanting your enterprise code viewable to the world. We are using Verdaccio on an on-premise server as our private registry.

The black lines represent a connection to a repository (we are using Bitbucket).

There is a small caveat here I’d like to point out. Take note how the black and purple lines for each row converge to a single line, therefore, a single repository for four components and a single package for four components (the number four is arbitrary). We decided to store similarly focused components into the same repos and packages because we knew we’d have close to 40 total components and it’d be troublesome to manage 40 repos and 40 packages. I’ll explain later how this works. Ultimately, you could break every component into a separate repo and package if that is your preference.

Code

The following pictures and code will be a glance at how all this works.

Here is the folder structure of multiple components in the same repository and how they are exported for use from the package.

index.js

The word “option” is arbitrary. It is a business term for our client, but you could interchange it with “component” because that is what each option is. Each component has its own folder where it is completely self-contained. It makes all of its own API calls, retrieves all of its own environment variables, and exposes inputs and outputs for communication.

In the package.json the build-option:all-options runs a Vue.js CLI command to create a library from all the components exported from index.js. Then all the code is placed inside the dist folder.

We then run npm publish to upload the components to our private registry. From there we can run npm i --save <package-name> to use the package in our application and then we treat it like any other NPM package.

It’s that simple.

Just kidding, there is of course more to think about:

How do you test each component?

I created “playgrounds” to test each component such that the playground is very similar to how an application will use the component. Running vue serve spins up the component on localhost:8080 to test.

How do you handle environments? The packages are pre-built so how do they switch environment variables before builds?

This was the most difficult problem I ran into and after hours of various methods I was able to accomplish dynamically setting environment variables in a pre-built package. I will probably write a follow up article on how I accomplished it.

You probably have a lot more questions and I would be glad to answer any in the comments. My contact information is also at the bottom.

Final Thoughts and Gotchas

I’ve grown to really like this architecture, but I’m not oblivious to the problems you could run into.

  • Kicking off new builds without code changes to an application only works if your packages don’t change major versions (e.g. 1.2.3 -> 2.0.0). If you change the major version of a component then you’ll need to update the version of that component inside your application’s package.json.
  • There are deployments processes which will vary depending on your CI/CD product, however, it should be very similar across different CI/CD products. We use Jenkins. For example, to use a private npm registry you must expose a .npmrc file in the root of the build. Accomplishing this may vary with different CI/CDs.
  • You need to be 100% dedicated to this architecture. One foot in, one foot out will not work well.
  • I would probably convince you to not use this architecture for smaller projects as the benefits don’t overcome the complexity. Always make sure to evaluate if the micro-component architecture suits your business and technical needs.

Again, what is the purpose of this? Our developers can write components independent of each other, we can push updates to to our application(s) without any code changes, and all the components are designed for reuse and can used in any number of applications.

About Me

I work for Orange Bees, a software engineering consulting company in Greenville, SC, as a Principal Engineer. I write Angular and .NET applications, architect projects in Azure (Azure Developer Associate certified), and dabble in ElasticSearch and Node.js.
You can find me on LinkedIn.

--

--

I work for Orange Bees in Greenville, SC as a Principal Engineer. I have a BSCS and MS in Computer Science from the University of South Carolina.