After months of careful planning, experimentation, designing, and testing, G2 Components is at a stage where all of the various systems and parts are coming together. The next phase is to integrate with Gutenberg (hopefully!). Integration planning is one of those hyper important things that is often left to the very end. It’s a crucial aspect that ultimately determines the success of a project like G2 Components.
UI Integration, and all of its nuances, constraints, and pitfalls, is something that I was well aware of before even starting down this G2 Components path. Many of the core mechanics and systems of G2 have been shaped around these considerations.
Update All The Things
Web UI is, for a lack of a better term, “delicate”. Integrating or upgrading to any new UI framework or library often feels far more laborious than expected. Styles often clash and cascade in a way that works against you, unexpectedly breaking previous interactions and disrupting newly built features.
Integrating UI libraries often feels like an “All or Nothing” event. Either everything works because everything is built on top of these libraries, or everything breaks because the side-effects introduced by these libraries. Anyone who’s had to introduce something like Bootstrap into an older/already established codebase would know these issues all too well.
The library would be loaded globally, effecting random UI things in random ways. There will be many (many) iterative rounds fixing “all the insert-UI-name“. Starting from general foundational elements (like Buttons) and slowly working your way to more specific UIs on specific pages.
I’ve personally experienced (shudders) this many times in the past. It’s a long, laborious, and painful process. Thankfully, these experiences have provided me with some insight and an alternative strategy to the blanket “update all the things” approach!
Update Some Of The Things
Ideally, what should happen is you should update just some of the things in a very controlled and intentional manner. It sounds obvious, but this approach is often very difficult to execute. It comes down to the fact that it is extremely difficult to create and integrate UI parts with zero dependencies and zero side-effects.
In other words, the new Button should not rely on anything from the current environment. No global styles, no resets… nothing. It should be 100% self-sufficient and should work out-of-the-box. This Button should also not affect anything when it is rendered within the UI. Whatever styles or scripts it introduces should not affect anything else on the screen.
Even then, having zero side-effect components is not enough. For example, blindly updating the older Button with a new (theoretical) zero side-effect Button would still result in unexpected catastrophe.
Below is an example of me replacing the WordPress Components Button with the Button from Material UI.
Blindly replacing it with G2 Component’s Button doesn’t fare any better.
No. We need something else on top of this. Something to help us segment and control these updates.
Section By Section
The best way I can illustrate this strategy is with an analogy.
Imagine if Gutenberg’s UI was a city. Within this city, there are various areas (like Gutenberg’s sidebar or top bar). Within these areas, there are many homes (like a Gutenberg Button UI).
(I must preface this by stating that I don’t know anything about city planning or power grids. I’m just using my imagination, haha).
At the moment, all of these homes (Buttons) are powered by energy provided by a power plant (e.g. WordPress Components).
Let’s say our goal is to power our homes with greener energy.
We can’t just force everyone in the city to update their lightbulbs. No, that would far be too disruptive. Instead, we have to introduce our new solar energy (e.g. G2 Components) in a way that’s as invisible as possible.
As we’ve learned, blindly adding the new implementation may cause unexpected side-effects. We need to make these upgrades in a controlled way.
Perhaps we start off with just a small section of the grid. We flip on solar energy for them and make sure everything works as expected.
If it does, we’ll continue to expand to larger and larger sections of the grid. Continue to test, observe, and resolve potential issues that may arise. We do this until we eventually convert all of the homes (again, without anyone having to do anything).
Once everything has been converted, we can then safely turn off the power plant.
This intention, controlled, and incremental strategy is how I’m envisioning G2 Components is rolled out into Gutenberg. This strategy can be achieved by leveraging one of G2’s core systems, the Context System.
The Context System will allow us to control and communicate which sections and which components should “flip” between the previous WordPress Components version and the new G2 Components version. Most importantly, it can be done in a way that doesn’t involve use ripping out or majorly refactoring component code.
All of this is quite abstract still. I’ve prepared a little technical demo to describe some of the principles of this “Section by Section” strategy.
Here’s the link to the CodeSandbox demo showcased in the video.
As an early test, we were able to render the new G2 Components within a tiny part of the Sidebar with zero disruption to the current components.
Having a thoughtfully constructed Component library is great. However, it doesn’t mean anything if it is unable to be used within the desired application. It’s not enough that the G2 Components code exists. We must also have a viable way to safely upgrade to the new stuff with minimal disruption to the current system and workflow. Many of these considerations were made before the first line of G2 Components was written. Hopefully, it will all come together when the time comes!