The NYTimes.com redesign is more than a fresh coat of paint — in addition to the new look, our article pages also rely on a new framework and codebase to run faster while making future changes easier. Reed Emmons, the development lead on the project, explains how we made this possible.

It’s rare to have the opportunity to start from scratch on a site like the NYTimes.com, and when I say scratch, I don’t mean just a design refresh, but a complete reinvention of the entire digital platform. The last visual redesign of the NYTimes.com occurred in 2006, but we’d have to turn our clocks back to the beginning of the millennium to find the last equally expansive infrastructure change. We decided to re-architect the client- and server-side in order to accommodate new product, design and newsroom requirements, such as faster performance and responsive layouts. Although some of the existing code was retained and heavily refactored, most of the code was removed and used only as a reference.

Slide Show

Publishing static pages: A history lesson

Until today, the majority of our content consisted of static HTML files living on hard drives in our data center. Our rendering system would write an HTML file to disk only when a producer chose to publish an article. We had our own proprietary HTML, which contained placeholders for dynamic widgets that were added to the page at runtime. When an article was requested, the rendering system would inject ads and prerendered templates into the page. It was fast and could handle enormous traffic spikes, so it wasn’t advantageous to move away from it until recently.

One of the major downsides of using our old architecture was its limited dynamic capabilities. Since the article’s HTML was fixed but the scripts and stylesheets inside it were dynamic, our front end team needed to maintain every template version that had ever been created. This is why an article published two years ago is a bit different than an article published a few weeks ago. Soft launching backward compatible CSS and waiting for it to uncache in every browser before launching a JavaScript change became common practice.

A front end architect on the project, Eitan Konigsburg, presented a deeper dive into our history at one of our TimesOpen events last year.

A smarter layout

To accommodate a smarter design, we built our own responsive JavaScript engine, which enables us to support a large number of breakpoints without using any CSS media queries. The engine enables the responsive design by toggling viewport classes on the HTML tag at specific breakpoints. Combined with LESS, this allows for elegant code that can be much more easily maintained and also supported by browsers that many of our readers still use. While its transformation sometimes is subtle, the article page adjusts over 20 times depending on the size of the browser or device. For example, the following snippet of LESS uses our responsive viewport classes:

.ribbon { ... // responsive // 1020 .viewport-medium-50 & { .offset(0, 1, 0, left); } // 1200 .viewport-large-20 & { .offset(0, 2, 0, left); } }

In addition to responding to breakpoints, the framework makes a series of choices about how to render the layout depending on the type of media in the lede position, the orientation and size of the media, and whether an advertisement is directly sold or purchased on an exchange. Taking breakpoints into account, an article page has over 100 variations.

Adding structure to our JavaScript

The redesign required a lot of JavaScript to be written to support a dynamic and personalized feature set. A robust framework was necessary to enable modules to live together without being tightly coupled. Backbone.js and RequireJS provided structure and a standard way of writing code. We chose Backbone because it provided a desirable amount of flexibility and is less opinionated than other frameworks. jQuery, Modernizr, SockJS, Underscore.js and Hammer.js were supporting libraries, and we also took advantage of Mocha and Chai to supply test coverage to our modules.

A few techniques we used when developing our framework were:

Using Backbone mixins to decrease code duplication.

Extending all Backbone views (and models) from a base view.

Throttling/debouncing expensive events like scroll and resize.

A new PHP rendering framework

The switch to a dynamic platform required us to use a new rendering engine that could quickly serve a large volume of articles on demand. Existing PHP frameworks provide a solid foundation, but we opted to build our own. It was customized to serve a large variety of content and had the major advantage of being conceived and built with increased flexibility in mind. Thanks to this, our framework has the ability to dynamically render different layouts and configurations on the same page.

The new framework simplified development and provided the means to create powerful applications with a few lines of code. Application development now typically consists of gluing existing components together, a process which significantly decreased development time. In addition, the library of modules available was created to be clean and simple, benefiting from a set structure and minimal code duplication.

Speeding things up with server-side caching

With dynamic articles being served, our technology platform needed a strong reverse proxy to protect the PHP rendering framework from being pummeled. The successful launch of Varnish on the NYTimes mobile site last May gave us confidence that Varnish was the best technology to use for the new platform. Varnish is highly configurable and provides lightning fast response times when serving content from the cache. It also enables us to cache our articles so those that change more frequently will stay in the cache for a shorter time.

Build process and front end performance

Using Grunt, we optimized our code to make fewer requests. Our article pages now contain three minified script and CSS files that are downloaded synchronously, a significant decrease from the approximately 80 non-minified files that were included in the HEAD on older articles. At the bottom of the page, we use RequireJS to asynchronously load several build files that handle the majority of the front end rendering. A cookieless CDN and cache headers set to one year guarantee that our readers will download significantly fewer bytes than before. With Varnish, our article page reaches DOMContentLoaded consistently between 500–1000 milliseconds.

All script tags are blocking, so one of the largest performance improvements came from loading ads asynchronously. Since ads are notorious for including document.write, we can’t simply add the code directly to the DOM without risking an overwrite of the page contents. Instead, all ads are bound within an iFrame and added when DOMContentLoaded is fired, which prevents the page from potential rendering issues.

The build process also generates other magic for the front end framework to leverage. We store all of our icons in a “sprite-me” folder so that a custom Grunt task can export a sprite sheet and a LESS mixin file that provide easy access to the compiled image coordinates. Finally, we use Underscore to precompile HTML templates so they can be easily “required” by modules and quickly rendered by the browser.

Closing remarks

Today, the new platform consists of newly published articles and interactive features. We’re still rolling these changes out (blogs, for example, will be migrated to the new architecture soon) and our new platform allows our team to iterate much faster and move closer toward our goal of continuous delivery. Although we are not entirely free from technical debt, we have built a solid technology platform that enables developers with a variety of skill levels to contribute to the codebase.

In the future, other members of our team will dig deeper into the technology used to build this platform, ranging from WebSockets to the PHP framework.