Enterprise JavaScript
Warren Bickley, Senior Product Development Consultant
11 January 20235 minute read
JavaScript is the most commonly used language for the tenth year running (according to Stack Overflow’s 2022 Survey) with the top 5 most wanted frameworks and technologies consisting entirely of JavaScript solutions. Investments from the likes of Meta & Microsoft into React & TypeScript respectively have helped to push the language forward and increase its popularity.
Continued advancements with Node.JS, Electron, and React Native, mean that practically anything can now be built with JavaScript - including the user interfaces for rocket ships.
JavaScript is uniquely positioned because of its ability to sit entirely across a technology stack without requiring additional client-side runtimes; clearly separating interface and API layers whilst still using a single common language. What seems a small and simple difference shifts what teams can achieve and as such serves as an opportunity to re-think how we approach headless development.
Ten years ago product teams need not worry about the challenges of developing solutions for smartwatches, vehicle media displays, smart speakers, games consoles, or smart TVs. In today's world, consumer applications are accessible across a broad range of devices and as such optimising teams to more efficiently deliver on multi-channel projects is essential for long-term success.
The growth of JavaScript across platforms and deliverables means that “write once, run anywhere”, a slogan once dreamt up by Sun MicroSystems for Java circa 1995, has now become incredibly apt for JavaScript. Whilst Java certainly dominated single-language cross-platform deliverables for over a decade, the rapid expansion of web browser-enabled devices and capabilities of JavaScript saw its inevitable decline for usage in web software and solutions.
The creation of Node.JS, Electron, React Native, and cross-stack frameworks such as Next.JS has meant JavaScript can be packaged for servers, native software, browsers, and native apps alike - freely sharing code where required. Sharing code across deliverables in this way has meant that, where suitable, dependencies such as shared rules, data sets, or internationalisation strings can move from run-time to build time - de-risking solutions by reducing the number of points of failure in production.
JavaScript has been maturing for 26 years, it has only been available server-side for half of that and for native applications via React Native for less than 8 years. The past few years have seen exponentially more stability and choice across the ecosystem. Particularly when paired with the popular TypeScript superset developed by Microsoft; introducing type safety and the possibility of end-to-end type safety.
This rapid growth has created a cycle of change within the ecosystem which is faster than any other, forcing companies and teams to consider how they move away from rich but constraining frameworks towards collections of open source libraries - enabling solutions to evolve with technology and avoid costly re-writes. Leveraging different parts of the JavaScript ecosystem where valuable and in a way which keeps components isolated enables teams to maintain velocity and stay current by always keeping space for new technology. This mantra means that should part of the deliverable stack become obsolete or old-hat, it can be swapped out over time; thanks to this businesses can keep pace with current technology whilst ensuring stability in the current service, allowing them to continue to attract candidate developers who share their passion for innovation and improvement.
Multi-channel delivery in 2022 goes hand in hand with headless architecture; headless architecture is the new normal for organisations and technical products of all sizes, separating core business logic into one or more APIs and having individual deliverables (typically being interfaces such as websites and mobile apps) which interact with those APIs.
Headless architecture is widely accepted as a sensible default choice for businesses looking to scale their technical success with increasingly more channels over time, at the cost of a typically slightly longer delivery timeline on the first implementation.
Whilst headless development has its advantages for scaling, it does come with its own set of challenges.
Redefining definitions, rules, and even logic across a headless stack can become tediously repetitive. Where inputs and responses might be defined within headless API validators and serialisers, consuming interfaces will also need identical definitions. Prior to the popularity of JavaScript, this was seldom often sharable due to the platform and implementation differences across deliverables.
Within headless teams that are delivering a single product together, changes required across the stack mean individual tasks are often blocked or impaired by resource requirements. This can be a pinch point during active development; often needing to scope API changes to a high degree of certainty and well ahead of interface changes.
This is particularly noticeable in teams where the stack differs between the API and user interfaces, as even where a UI or API engineer does have the autonomy to make changes across the stack they may not have the relevant understanding or experience to do so.
JavaScripts super-power is the ability to write the same code for our APIs as most of our interfaces. With the right architecture and team structure a small nimble team of cross-stack JavaScript engineers can achieve what would otherwise require a multi-functional team of engineering specialisms, done well there are zero compromises on deliverable quality with a huge reduction in both work and required communication.
Modern user interface development sees us now doing a lot of work on the UI that previously would have run exclusively on the backend, particularly with regard to input validation. This means that within a lot of ecosystems, there is a duplication of schemas, validation rules, types and even logic across the application stack; any potential inconsistencies in these duplications can introduce risks. For every additional interface interacting with the same API, that risk is drastically increased.
Instead of duplicating this code, it can be shared across the API and interfaces as a source of truth. Within an entirely JavaScript ecosystem this is fairly straightforward; achieved either with a Monorepo encapsulating all packages or by publishing to a package registry.
If you’re developing an API alongside your deliverable UIs, as is often the case with headless development, then the former approach of working within a Monorepo is generally superior to publishing packages to a registry. Changes are reflected across the stack instantly and this allows engineers to tweak either side as required as opposed to waiting for each other to implement and publish changes. This offers a superior developer experience and improves cross-stack awareness and capabilities with all engineers.
An alternative approach is to generate consuming packages from API code, whilst this requires much more configuration and a strictly declarative approach to API definitions it does grant far more capabilities. This approach is particularly well suited to APIs which require third-party availability given it can output more than just JavaScript or TypeScript packages.
With an approach such as this, documentation and API definitions are generated from API code so require little to no maintenance. The always up-to-date documentation, debugging collections, and API definitions, make it much easier for anyone to integrate with the API (internal and external) - even if they’re not using JavaScript.
Having all of these resources available at the start of a new integration would enable teams to get new projects up and running incredibly quickly, and enforce consistency via end-to-end type-safety. In contrast to solutions currently available within the JavaScript ecosystem, it would enable teams to develop APIs which are decoupled from their web deliverables but keep the same level of reliability across the stack and further.
The benefits of accelerating JavaScript development are synonymous with that of having a good developer experience, as should be an ever-moving target technical teams chase in order to keep engineers satisfied and project velocity uninhibited. Reducing duplication across the application stack means that teams get to focus on the work that makes a difference. Less monotony in their work reduces the labour intensity and improves their overall satisfaction working on a project.
Thinking more about how code can be shared across the stack and how run-time dependencies can be reduced equates to deliverables which are less prone to errors throughout the SDLC, thus time-to-delivery is greatly improved. This isn’t just down to the reduction of work however, the reduction in required communication to make changes across the application stack allows individuals to move with greater autonomy and fewer roadblocks.
The overall reduction in complexity across the stack also makes it easier for engineers to move between deliverables, thanks to this junior staff will be more productive and the time required to onboard new engineers will be significantly shorter.
Thanks to its ability to run anywhere, and the exponential increase of web-capable devices, the JavaScript ecosystem is going to continue to be the go-to place for architecting new cross-stack multi-channels solutions at startups, scale-ups and enterprises alike. Its developer experience and code-reduction capabilities of it make it the right choice for teams who want to move fast and deliver robust solutions.
Enter your email below, and we'll notify you when we publish a new blog or Thought Leadership article.