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
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:
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.
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.
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.