Enterprise JavaScript
Dan Curtis, UI Manager
14 February 202310 minute read
Anyone that has been involved in any sort of UI development knows the challenges we all face with the plethora of UI libraries/frameworks that are available, all with different offerings that promise better performance, better developer experience, and being ‘the next best thing’.
React has very comfortably taken the top spot over the last 5 years, that is undisputable, and is likely to remain the case for the next few years to come, but what if you aren’t on React right now? What if you need a way to migrate to React bit by bit? What if you are considering React but don’t want to have to rewrite everything again in a couple of years?
A common problem (and this applies to any technology), is that you want to be on the upward trend so that your choice has the best return on investment, too early you risk it not gaining traction, and too late you risk having to support legacy technology. What if there was another way? What if you could mitigate that risk?
These are the questions we continually ask here at Griffiths Waite, and we’re always working for better ways to facilitate pivots in technology.
Back in 2015, Oracle threw their hat in the ring with a front-end JavaScript development library. Named Oracle JavaScript Extension Toolkit, also known as ‘JET’. The promise was a library that helped to settle the turbulent JavaScript ecosystem at the time. The likes of Angular, React, and Vue were all battling for that top spot. The concept from JET was simple, pull together existing open-source libraries and produce an extendable toolkit, leaning on the web component spec to allow for interoperability with different libraries.
For anyone coming from a background of a locked-in framework, such as we were with Application Development Framework (ADF), JET was a breath of fresh air. No more spinning up hefty local servers just to run our UI, we can click save and see our changes instantly – amazing!
We adopted JET early, even before it introduced web components, which meant that we had to go through some of the pain that it went through itself as it was trying to figure out what it was and where it was going. We were there for the early years, the move from data-bind
to web components, the introduction of TypeScript, the OJET CLI bundling changes, and many component and feature deprecations including the widely used Alta theme. In truth, JET today is in a better place, the choice to ditch knockout in favour of Preact is a good one, and so is the eventual webpack support. But it is too little too late, and the lack of community adoption puts it in a very difficult position with little to no future.
After using JET for 3 years on projects, we faced two big problems:
When looking to adopt new technology and backing one that will either succeed or fail, you have to consider its barriers to success. What advantages does this new standard or technology provide? Do the advantages outweigh the drawbacks? Adoption will be higher when there is less friction to move fast. Web Components, certainly in the JET Composite ecosystem, did not deliver fast enough to warrant their use.
Part of the issue with web components is that they were aiming for a common standard across the board of browsers and technologies. This takes time. Time is something that you don’t have in the JavaScript ecosystem. The libraries that we use today haven’t waited around for this standard to be adopted and instead gone ahead with their variations of components. Their implementations also being significantly quicker to develop, with a better developer experience and less friction to change has resulted in little to no need for the adoption of web components.
The promise from web components is still compelling though, an agnostic standard that doesn’t tie you into a particular library or framework. It’s would be great for future proofing applications and switching between technologies, but it can also stagnate growth if the UI libraries of the future are limited to the slow movement of a W3C spec.
What if there was another option? An option that worked cross-library, that was an agnostic concept, and wasn’t even a component at all?
With our React applications, we have been using a suite of tools named ‘Tanstack’. These were developed by a prominent community contributor Tanner Linsley. The Tanstack of libraries currently consists of a table, query, charts, virtualiser and location. Last year some big announcements were made alongside table v8 that revealed an important insight into how we should look to develop components and applications of the future.
Tanstack uses an approach called headless UI, which is an architecture that involves moving the logic, processing, events, and state outside of the markup and UI of a component. So all of the complexities that a ‘component’ needs are abstracted into a function (or hook). The ‘complexities’ should be seen as a toolbox, they give a developer everything required to build a component, but not the component itself. Doing this gives full control to the consuming developer, they can build a component in any way they feel fit for their requirements, using any styling library they wish and even extending it to support any features they feel are missing. They get the full control that they would miss from a traditional component and a better separation of concerns between rendering and non-rendering logic.
This of course comes at a price - there is more of a setup cost. You lose that ‘plug and play’ approach you can get with a traditional component. However, even with the headless approach, there is no reason why a component cannot be provided alongside the toolbox. Why not get a component and all the tools to build your own if you need to?
Figure 1 - Headless UI
Tanstack has used the headless approach for several versions now, it really took off with the introduction of React hooks. But this year it was taken even further. React was dropped as the prefix for all of Tanstack libraries, and instead, each one has an adapter to use with React, Vue, Solid, Svelte or even Vanilla JS. This has all been possible thanks to the headless UI approach.
After adopting JET as our preferred UI technology choice back in 2016, we soon figured that Oracle JET did not offer us the scalability that we needed for our projects. After already undertaking a ‘big bang’ rewrite for one of our clients from ADF to JET, we couldn’t justify another full rewrite so soon, but we also saw a lot of risk with staying on JET over the near to medium term.
To avoid a complete rewrite, we took another approach, we built a new integration adaptor that provided a straightforward co-existence layer between JET and React with a great developer experience. To be clear, this isn’t ‘micro-frontends’, this isn’t an iframe approach, and this isn’t a Frankenstein multi-library application. It is a lightweight adapter that facilitates different JavaScript libraries working together in a single application.
We have found that this is a clean approach to using JET and React together, with communication and session sharing across the two libraries. See below a comparison between micro front-ends and the GW integration layer.
In this application, JET is the host - it owns the application state. The integration layer sits within React and upon mounting it takes the JET session state, strips all the observables away and stores the state as a pure JavaScript object within React state. At the same time, it also loops through the JET observables and subscribes to them, we do this so that when the JET session updates we can know of the change, and update the reacts equivalent state too. We have a listener on the React session that will do the same in reverse, it will listen to any changes to the React session and update the JET observable. Figure 2 below highlights how this works.
Figure 2 - Integration Layer Session Sharing
Using this layer, and build tools such as webpack, we can have a fantastic developer experience, multiple UI libraries with clean communication, and a seamless runtime output to the users.
Figure 3 - Integration Layer in an Oracle JET Application
Above is an example of where this is used in a production application. The area highlighted in red is written entirely in React. It sits within the same codebase as the host application and shares API references, types, and state with the host. The communication between the two, for things such as sharing currency, or sharing the selected state from the component above is all handled using the integration layer that we show in Figure 2.
Figure 4 - Proof of Concept showing JET, Preact, React, SolidJS and VueJS all working within a single application
The integration layer was built specifically to support React, which works well. We soon realised that we can easily scale this further and use the same approach for other libraries. To demonstrate this, we built a small POC to showcase that we can get JET (and Preact), React, SolidJS and VueJS all running within a single JET application, sharing state and dragging and dropping state changes between each other.
Figure 4 shows an animation of this demo.
At Griffiths Waite we pride ourselves on being Enterprise experts, we have long-running relationships with our clients that can span decades. We have always been trusted with building enterprise technology but not staying stagnant, by moving forward and innovating wherever we can. Enterprise should be able to be used in the same sentence as innovation.
We recognise that the bigger and more complex a system gets, the harder it is to replace, which is why enterprise software can be harder to maintain. Enterprise solutions cannot stand still, from a technology perspective they need to continually evolve otherwise they will start to fall further and further behind the industry until an organisation is left with little choice but to undertake a very expensive and high-risk rewrite.
Sustaining innovation means meeting the challenge of coexistence, but in doing so it avoids the ‘Big Bang’ replacement projects we see too often. We have always pushed for solutions to this challenge and with what we have already delivered into production for clients, and our plan to extend this even further, we can give you a migration path from your current estate, not only to something better today but prepare you for the future too.
With the adoption that we are seeing with headless UI, combined with what we are already doing in our production code for existing clients, we see a path forward for managing the rise and fall of JavaScript UI libraries in an economic and frictionless way.
Enter your email below, and we'll notify you when we publish a new blog or Thought Leadership article.