Airbnb’s Trip to Linaria

Learn how Linaria, Airbnb’s newest choice for web styling, improved both developer experience and web performance

From Sass to CSS-in-JS

In 2016, our web frontend was in a monolithic Ruby on Rails app using a combination of Sprockets, Browserify, and Sass. We had a Bootstrap-inspired internal toolkit for styling, but we weren’t using anything like CSS Modules or BEM.

Considering Our Options

To address the problems with react-with-styles, we formed a working group of engineers from various teams. We considered a number of directions, which fit into the following high-level categories:

  • Write our own framework
  • Investigate and adopt an existing framework
An xkcd comic titled “How Standards Proliferate: (see: A/C chargers, character encodings, instant messaging, etc). Panel 1: Situation: There are 14 competing standards. Panel 2: “14?! Ridiculous! We need to develop one universal standard that covers everyone’s use cases.” “Yeah!” Panel 3: Soon: Situation: There are 15 competing standards.
Comic from https://xkcd.com/927/ by Randall Munroe and is used under a CC-BY-NC 2.5 license.
  • Linaria: zero-runtime CSS-in-JS (static CSS extraction)
  • Treat: near zero-runtime CSS-in-JS (static CSS extraction)
  • Try out framework APIs and get a feel for developer ergonomics
  • Assess how each framework supports our web styling requirements
  • Gather performance metrics
  • Serve as a starting point for a migration plan
  1. Community (i.e. support and adoption)
  2. Developer experience

Performance Analysis

Using SpeedCurve, local benchmarking, and the React <Profiler />, we ran performance benchmarking tests for each framework. All results were calculated as the median of 200 runs on a throttled MacBook Pro, and are statistically significantly different from control with a p-value of <= 0.05.

What We Liked About Linaria

The above performance improvements were largely thanks to Linaria extracting the styles from JS to static CSS files at build time, so there is no JS bundle or runtime CPU overhead — giving it a slight edge over the near-zero runtime Treat. Also, this brings caching benefits since these static CSS files may change at a different cadence than the JS files. Since the styles are extracted at build time, Linaria has the opportunity to automatically remove unused styles — this also opens the door to the possibility of deduplicating styles (i.e. Atomic CSS). Additionally, Linaria supports injecting the critical CSS for server-side rendering, which we had wanted to preserve from our react-with-styles integration.

Off-the-shelf integrations for stylelint, CSS autocompletion, and syntax highlighting working with Linaria in action.

Migration Strategy

To roll out this big change, we adopted an incremental migration strategy that is largely automated by codemods we’ve written. We are leaning heavily on our Happo screenshot tests to ensure that our components look the same after they are migrated. This allows sections of our codebase to be migrated by running a script and following up with any necessary tweaks, similar to the approach we took when adopting TypeScript.

Contributing Back

Once we started using Linaria, we discovered that automatic style deduplication (i.e. Atomic CSS) would give us not just a performance boost, but also would fix some non-performance-related hiccups we ran into.

Reception

Our engineers have reacted positively to Linaria. Here are some quotes:

Performance Impact

Though we are still at the beginning of our migration, we have run some A/B tests that give us an encouraging look at the real world performance impact of switching to Linaria for a large group of visitors in the wild.

What Does This Mean for react-with-styles?

Given that we still have many components that still depend on react-with-styles and that it will take a while for us to complete our migration, we will put react-with-styles in maintenance mode until we approach the end of our migration. At that point, we intend to sunset react-with-styles and the related packages.

Conclusion

Styling infrastructure is still an exciting space, rich with opportunities. At Airbnb, we’ve found big improvements to the developer experience by adopting a framework that allows regular CSS syntax to be used alongside our React component code. And by replacing a runtime styling library with one that compiles to static CSS files at build time, we are able to continue driving toward faster performance. Thanks to the Linaria community and our collaboration, we expect this library to continue to improve for many years.

Acknowledgments

We have a lot of appreciation for the folks at callstack and the Linaria community for building such a great tool and for collaborating with us to make it even better. Also for Khan Academy for giving us Aphrodite which served us well for many years. This has been a huge effort at Airbnb that would not have been possible without all the work put in by so many people at Airbnb, including Mars Jullian, Josh Nelson, Nora Tarano, Alan Wright, Jimmy Guo, Ian Demattei-Selby, Victor Lin, Nnenna John, Adrianne Soike, Garrett Berg, Andrew Huth, Austin Wood, Chris Sorenson, and Miles Johnson. Finally, thank you to Surashree Kulkarni for help editing this blog post. Thank you all!

--

--

Creative engineers and data scientists building a world where you can belong anywhere. http://airbnb.io

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Joe Lencioni

Web infrastructure at @airbnb. Making web since the 90s. Co-created happo.io. he/him Minnesotan, liberal, dad. Follow @lencioni on Twitter.