Pemberly at LinkedIn
December 2, 2016
When setting out to re-imagine our flagship app and desktop web experiences last year, we wanted to make a move to a more modern technology stack. We were falling behind in a few areas and wanted to address the following points of concern:
Modern web apps are typically heavily client-rendered to provide the user with a more responsive user experience. The design team wanted to create page transition experiences, which are not possible in traditional web pages. When a traditional web page is requested, the browser loads it suddenly and jarringly as the response is fulfilled. Conversely, in a client-rendered app, transitions can be made to elegantly fade or slide in, because the Document Object Model (DOM) of the existing page is being replaced rather than a new page being requested from the server. Also, we wanted our desktop member experience to be more app-like and aligned with the native mobile app experience both for consistency between platforms and snappy-feeling interactions.
The solution: Pemberly
As we were going to support sending data directly to the browser, we needed a way to make our API open to HTTP requests on the internet—of course with all the proper handling of user authentication. We decided to build an API server that could be shared by web and mobile clients for a consistent experience across platforms; in other words, to build once for the UI and use in multiple clients. In order to provide the appropriate filters and access control, we leveraged our Play mid-tier architecture. Typically, our Rest.li APIs are available in the data center via D2, a protocol for discovery of services by clients. The API server transforms these requests to standard JSON and exposes them to the internet. In addition to security and internationalization capabilities, the API server provides conveniences like mocking and replay of responses for writing robust unit tests of the APIs.
Base Page Renderer
The next piece of the architecture is the Base Page Renderer. The Base Page Renderer provides the head of the document and early flush capabilities. It also allows the app to load in several modes: Vanilla (browser does the heavy lifting), SSR (server-side render for DOM complete), and BigPipe (the ability to let the browser boot the Ember app while simultaneously streaming data and DOM to the browser by delegating that work to separate Node processes, which are running the Ember app).
Ember is our browser-based application framework. Ember provides a set of robust conventions for developing apps and managing data and state within the apps. It also provides an ecosystem of tools including a CLI and a rich unit, integration, and acceptance testing framework. Ember runs all the business logic for the app after the initial page load is brokered from the Base Page Renderer. Consistent entities and API writes are managed through Ember Data. We are also pushing the bounds of what can be done inside the Ember ecosystem with the new Glimmer2 rendering engine and loading engines lazily or eagerly in production.
ArtDeco CSS library
The last page of our ecosystem includes ArtDeco, which is our internal library for consistent styling (and sometimes interaction) of web page elements. Built on top of Eyeglass, a Sass extension ecosystem, ArtDeco is distributed as an Ember CLI add-on, seamlessly integrating into the Ember build tools. This final layer gives us a consistency of user experience and visual styling across different products with a high level of re-use in the CSS layer.
Along with re-imaging the user experience of our flagship app, we’ve also completely re-imagined the tech stack from CSS down to the APIs. We are incredibly proud of our ability to iterate quickly on our apps as well as to contribute back to a significant number of open source projects as we learn and evolve our ecosystem.
Huge thanks to the following, who helped us arrive at this architecture: Anand Bolini, Mark Pascual, Eugene O’Neill, Chad Hietala, Chris Pettitt, Krati Ahuja, Marius Seritan, Chris Eppstein, Prateek Maheshwari, Josh Fleming, Ashit Gandhi, and Nash Raghavan—and to the Ember community for providing us incredible support on our journey.