In previous blog posts, we talked about our new source map support for New Relic Browser as well as how to integrate that support as part of your build process. This post covers how we architected our own frontend, and how we integrated source maps as part of it.

At New Relic, we have constantly evolved our architectures and development processes to foster faster development cycles and better workflows for our engineering teams. This post covers our efforts to decouple our frontend from our backend services, and the workflows this has helped to open up.

Breaking down a monolith for flexibility

Originally, our JavaScript and CSS was part of the Ruby on Rails monolith that powered New Relic’s entire UI. As more application logic was moved to JavaScript, we found that we couldn’t release a fix for our frontend without the increasingly painful process of deploying the backend as well. To address this, the team started extracting the UI into separate repositories that could be deployed completely independently of the backend service, and this has created a lot of flexibility in our frontend deployment.

The version identifier for our frontend code is also a setting in the backend that can be updated at any time—without changing the backend source code. Since we develop the UI against relatively stable services on the backend, the frontend is decoupled and we don’t have to worry about keeping the two code bases in sync. The features for our UI are kept in separate repositories for the most flexibility, with the different versions of our code collected in an artifact repository that we store on AWS S3.

This graphic shows how it all works:

frontend architecture diagram

When the frontend makes a request, the system configuration variable CURRENT_VERSION helps the backend retrieve the right file from the artifact repository to pass to the frontend.

When the frontend requests code from our backend, the system configuration variables pull the correct version of the code from our artifact repository. This then gets passed back to the frontend. To manage these different file versions, our build system uses the release identifier in each of the file names.

Better workflows amid different frontend versions

The version identifier can also be overridden with a query parameter in the URL, allowing us to run any version of the code on any environment. We can even work locally against any backend environment that supports this functionality. That allows us to use real-world data to develop a new feature, without removing it from our secure production environment.

frontend architecture diagram

The system configuration variable CURRENT_VERSION is overridden by the query parameter to request a newer file version from the artifact repository.

When a New Relic engineer opens a pull request, our Jenkins server builds the updated version of the code and deploys the new version to a content distribution network (CDN). A Jenkins bot comments on the pull request with a preview link that can be used to demo the changes in any environment.

All of our frontend assets, including CSS, images, and SVG graphics, are versioned and deployed in the same way. The demo link can even be sent to stakeholders to confirm the desired behavior and style. We can also run Selenium tests against the pull request code to detect regressions.

When an engineer merges the pull request, the latest version of the code is automatically built and deployed to our staging environment, which we use to monitor our systems. This allows us to “drink our own champagne” and see the new functionality integrated. With the magic query param, we can even use the UI candidate in production to determine if it is ready for release.

Releasing new code to customers is a simple matter of updating the version setting in our production backend—no deploy required. If we happen to ship a bug, rolling back is as easy as switching to a known good version of the code. This overall build pipeline makes it pretty seamless for us to get our code to our users faster. On the New Relic Browser team alone, we push out dozens of changes to our users every day.

stack diagram

Integrating source maps at New Relic

This frontend architecture and the workflows that it makes possible have made life as a frontend developer at New Relic so much easier. We use webpack and Babel to bundle, transpile, and minify our code as part of our continuous integration process on Jenkins. Since we already had a robust build process, it was straightforward to add source map publishing. By adding a publishing step that runs on every successful build, we always have the latest source maps available in the New Relic Browser product.

sourcemap code

Because of the design of our architecture, every build is already uniquely identified with a version number, so it was just a matter of publishing the source map each time new code is deployed. It all comes together pretty seamlessly, letting New Relic engineers troubleshoot JavaScript as normal. We hope our approach gives you some ideas for how to optimize your own workflows.

 

Edwin Knuth is a senior software engineer on the New Relic Browser team based in Portland, Oregon. View posts by .

Interested in writing for New Relic Blog? Send us a pitch!