Skip to main content

REI's Front-End Build System (FEBS)

What is a front-end build system?

The front-end build system is tasked with building all of the JavaScript and CSS code that will ultimately be downloaded and run by the browser to render and control the user interface for a web page. Nowadays, modern front-end code is rarely directly consumable by the browser for reasons we’ll expand on below.

febs-diagram

As you can imagine, this becomes a lofty task when you consider all of the complex features that must be delivered, what browsers/devices/versions they must run on, accessibility, performant delivery over the network, load and run-time performance, SEO, device responsiveness, front-end technologies being used, unit testing/code coverage, etc.

Why do we need a build system?

Browsers themselves provide front-end developers with a fairly basic set of tools to work with yet the developers are often tasked with creating very complex applications that run within them. At a high level, you get the raw browser APIs, a JavaScript engine, a rendering engine, and the network application layer. That’s it. Writing complex applications, however, requires much more. This increased complexity of and rate at which applications and new features are needed by the business demand powerful tooling, technologies, and methodologies regardless of which part of the stack the developer works in.

On the frontend, some of the things we require are:

  • Meaningful organization of code into modules and/or components.
  • Smarter, well-organized CSS with CSS preprocessors
  • Code optimization for network delivery (bundling, minification, versioning, code-sharing, tree-shaking, bundle splitting)
  • Code source maps for debugging
  • Next-generation JavaScript and CSS syntax support
  • Code quality: Linting, unit testing, and code coverage


The front-end build enables all of this by:

  • Transforming code that developers write into code that the browser can optimally consume
  • Allowing the developer to build quality into the software that they produce
  • Allowing the developer to use future technology today

REI’s Front-End Build System

At a basic, high level, the front-end build system needs to perform some critical things, some of which are:

  • Bundle the JavaScript and CSS code sent to the browser
  • Minify and remove development code from bundles for production
  • Version the bundles for cache busting
  • Generate external sourcemaps for debugging transpiled/minified code


Additionally, there are many other desirable things that we would like to include in our build system such as:

  • Transpile code written in next-generation (ES2015+) JavaScript syntax into JavaScript that your supported browsers can execute.
  • Transpile your SCSS/LESS, etc. to CSS.
  • Run code linting to ensure code adheres to your organization’s style guide
  • Run unit tests and code coverage on JavaScript.
  • Generate accurate CSS browser vendor prefixes for your supported browsers
  • Performance optimizations: Bundle-splitting, bundle-sharing, tree-shaking, etc.
  • Publish build statistics for tracking build improvements and degradations over time


As you know from some of our previous Engineering articles, REI has been moving from monolithic to microservice/microsite application organization. FEBS 1.x, our first front-end build system, is what is responsible for building all of the front-end code that still remains within the monolith. FEBS 2.x, the next generation build system that comes bundled with an REI Alpine application, is what will be building all of the front-end code that lives in a microsite. It actually lives out in its own repository on GitHub as well as in the NPM registry so can be pulled into whatever application needs a front-end build system.

The primary goals of FEBS 2.x are:

  • A simple, easily configurable, maintainable, well-tested front-end build system with a minimal amount of code.
  • A build system that can be reused across all of our microsites rather than maintaining multiple custom or copied build systems that we must maintain.
  • A build system that encourages technological consistency in our front-end codebases.


There are many wins but one of the biggest is that the front-end developer is now freed up from having to spend time and energy re-inventing the build system wheel.

FEBS 1.x

FEBS 1.x, our first-generation build system, is what builds the front-end code that still lives within our monolithic application. It is based on a different set of core technologies, namely browserify and gulp. It currently lives within our core codebase and has really been optimized to build a lot of code quickly. It’s been through many optimizations, some of which are caching .js and .css bundles and skipping steps only needed for production builds. We typically get roughly 75% reduction in front-end build times with caching enabled.

An additional task that FEBS 1.x does is collect our build statistics such as bundle sizes of .js and .css files and unit test coverage percentages and sends them to to Grafana to track over time.

febs-js-stats

FEBS 2.x

With the move to microsite style architecture, we needed a build system that could be reused throughout all of our microsites. FEBS 2.x is our next-generation build system that is part of the Alpine platform. Any Alpine application that needs a front-end build system will come with FEBS 2.x. It was designed with developer productivity and our supported technology stack in mind and enables the developer to focus solely on writing application code rather than how it needs to be built.

What’s New in FEBS 2.x

One of the big changes is that we switched from browserify to webpack as the core bundler. Why the switch to webpack? Browserify served (and still serves) us well but the main reasons for the switch were due to its simplicity and huge development community that rallies around it. We now have literally hundreds of developers on our team helping us keep in step with the fast-changing front-end ecosystem. Additionally, we are part of that team that contributes back to its community.

Those familiar with webpack know about the in-memory dev server that can be set up. FEBS 2 provides this as well so developers can fire up their application with app live-reloading out of the box.

The production build performance optimizations around caching in FEBS 1.x are simply not needed anymore in FEBS 2.x for 2 reasons: (1) It’s building much less code, and (2) the built code will be published to npm so the larger parent web application will simply install it, not build it.

FEBS 2.x comes completely unit tested which is critical in that it is used across all of our microsites. The webpack config files can also become a bit dense with all of the loaders and their associated configurations making unit tests all the more critical. It utilizes an in-memory file system to validate actual build output so the unit tests run without the need of any file I/O.

Finally, the amount of code that we need to maintain is minimal. Comparing the two, FEBS 1.x is pushing 10,000 lines of code and FEBS 2.x is only around 300 lines.

Future

That wraps up this introduction to FEBS! Some of the things that lie ahead for us in the upcoming months are:

  • Support and incremental improvements as adoption increases
  • Integration with our CMS
  • Revisiting our unit test API for client code
  • Updating to webpack 4.x
  • Bundle sharing/splitting
  • Build stats


Feel free to pull it down, give it a whirl, give us suggestions, create some PR’s, etc.! We hope this was helpful and stay tuned for more updates and articles around FEBS!

< Previous Article Effective Code Freezes in a CI/CD World
Next Article > Jenkins As Code