Designing for Performance In Progressive Web Apps

How we achieved a speedy PWA experience from the project get-go by incorporating performance considerations into the design process.

Ben Groulx
Mobify Design
14 min readMar 17, 2017

--

Praise! The speed and ease-of-use of a progressive web app is a crucial piece of a great mobile commerce experience.

Progressive web apps (PWAs) are the future; they’re the next Big Thing®™ in web tech, or rather, they’re already here and we should all hop on board. In fact, in 2016 we at Mobify dropped developing mobile ecommerce experiences using our Adaptive technology and started working using Progressive Mobile — our solution to a single code base for both progressive web apps and native apps. From here on out, everything would be a progressive web app or progressive native app build from the get-go. 📲

Google has been pushing progressive web apps pretty aggressively, and I think it’s great. What I love most about their involvement is they are basing these mobile experiences on the principles of progressive enhancement, meaning it starts with basic functionality for everyone, but provides an enhanced version to anyone with a more sophisticated browser or additional bandwidth.

Designing for this new way of delivering a mobile commerce experience requires a shift in thinking.

This summer, I was tasked with redesigning a big brand’s mobile ecommerce experience using this new approach. Mobify did the initial build three years ago, and now it was time for a refresher using the latest and greatest. One of the project requirements was getting the mobile experience to deliver content to users as quickly as possible — after all, that’s why users to go your website: for the content. (From an ecommerce perspective, this is even more important: get shoppers to the products they want to learn about, and get out of their way as much as you can.)

Out-of-the-box, Progressive Mobile delivers a responsive mobile web app that progressively enhances the customer experience based on the capabilities of the device and browser. (Aside: Progressive Mobile is entirely a front-end technology, meaning we cannot control things like first byte time or keep-alive status — that’s all still handled by our client’s servers. It works as a layer on top of the desktop experience that blocks the site from loading, then uses bits and pieces from the desktop’s DOM to complete the mobile experience; essentially we treat our customer’s desktop sites like an API, calling in specific data or scripts to populate the shell we create.) It’s awesome for performance, overall; we’ve consistently measured improved page performance 2–4×.

Another benefit comes better coding standards; with Progressive Mobile, for example, the way we write code is significantly tidier than our previous technology solutions: 76 kb on average for stylesheets in Progressive Mobile (sample of three sites), compared to the 171 kb average from our previous Adaptive (sample of five).

So that’s great. But I wanted to know how we could improve performance over a typical implementation.

You may think: Is improving performance really the designer’s responsibility? As designer I want everything to load instantly! Surely, that would fall on the shoulders of my team’s engineers? Or at the very least we should be able to circle back at the end of the project and tidy some things to make it snappier?

I say: Yes, it is the designer’s responsibility — it’s everyone’s.

Performance is every team member’s responsibility from the beginning.

A website or app’s speed is a crucial piece of a great user experience. All the love and care you give to typography, colour, and layout means nothing if the shopper has already left before the page has finished loading. On user experience and performance, Lara Hogan, Engineering Director at Etsy, writes:

Your site’s experience determines how much your audience trusts your brand, returns to your site, and shares it with others. Page load time and how fast your site feels is a large part of this user experience and should be weighed equally with the aesthetics of your site.

So as a designer, how does performance affect my day-to-day? What can I do from a design perspective that would have a positive effect on my product’s speed?

Because the default installation of Progressive Mobile already addressed many issues, our biggest hurdle to overcome was from project bloat. Let’s take a look at why we care about bloat.

Why We Care About Bloat

Bloated sites cost shoppers time, money, and hardware processing — all of which we we want to use a little as possible on users’ devices.

Our customer’s desktop experience was impressively slow; their home page alone came in weighing a whopping 8.21 Mb. On a 12 Mbps LTE connection, it would still take a shopper about 9 seconds — yikes. 😣

There are numerous different takes on a stat like this, but I like Google’s take on it; according to Think With Google:

“The average U.S. retail mobile site loaded in 6.9 seconds in July 2016, but, according to the most recent data, 40% of consumers will leave a page that takes longer than 3 seconds to load. And 79% of shoppers who are dissatisfied with site performance say they’re less likely to purchase from the same site again.”

9 seconds is an exorbitant amount of time. So right off the bat, pulling in the entirety of the homepage content would cut the amount of potential shoppers nearly in half. A poor experience for shoppers is a terrible result for our customer; we need to deliver better results than that… ideally, under 3 seconds.

8.21 MB, clocking in at about nine seconds, unnecessarily costing people their hard-earned money… all because performance wasn’t a priority. All of this leads to a lot of room for improvement with our mobile implementation.

Additionally, when I look at how much that amount of data would cost the shopper, I am immediately pushing the stop-everything-right-now-and-rethink-this button. Almost a dollar for Canadians? That’s not only a detrimental experience, but it is unethical to essentially charge shoppers for viewing the your site’s content. While every web experience costs a little bit to view, the very nature of the web is open and accessible to all, and we should be doing everything in our power to preserve this.

Your desired aesthetic is not worth the hindering of getting to content or function.

Because we have no control over our customers’ back-end, we have no means of fixing things like load distribution or shared resourcing. That simply means we needed to be extra diligent on the front-end to make sure we are reducing bloat as much as we can. Luckily, with Progressive Mobile we can rebuild our own front-end, meaning we have total control over HTML, CSS, Javascript, images, etc.

I figured for the build we was working on taking care of two specific areas would give us the biggest improvement: stylesheets and assets.

Reducing Stylesheet Bloat

Dieter Rams once wrote, “Good design is as little design as possible.” I find this rings true in our approach to writing CSS. Less, but better.

Less, but better — because it concentrates on the essential aspects, and the products are not burdened with non-essentials. Back to purity, back to simplicity.

During the build, I would constantly check in on CSS Stats to see how we were doing. It’s a fantastic resource. Chris Coyier, CSS-Tricks/CodePen creator, describes it as:

Some heuristics on CSS that you can run on any site. Started with the sharing of that data from several popular sites. It’s open source and I would think the most valuable feedback to give would be “What data would be useful to know about your CSS?”

I tried running the original mobile build through it — the one built ~3 years ago. What we get is a collection of data points that makes me weep. 12.3k declarations? 1,000+ of those are just for font-size? 😨

Throughout the new build, we would use CSS Stats to make sure we weren’t duplicating unwanted code. The wonderful thing that this showed us is that code standards can go a long way to fixing unneeded repetition and unnecessary rules. But there’s only so much can fix.

Standards tell you how best to write code, not how to think about it.

To fix that we had to reconsider how we were applying our styles — and that began with the creation of the design system. On the topic, Facebook designer Daniel Eden writes:

Design systems break as they scale because new components and variants are introduced. Those variants often go undocumented, leading to duplication. Even when the component is documented, documenting effectively often means dozens/hundreds of instances to capture all states/variants.

Daniel’s quote here about variance is noteworthy: the more divergence there is in the aesthetic of a component or a template, the more code needs to reflect these changes.

This is especially problematic for a strictly component-based framework. We use a modified version of BEM that we call CSM (component-subcomponent-modifier): This naming convention reflects the way we think about our designs: independent, self-contained units of an interface that can scale together. When we go to write the CSS for them, all styles belonging to a component only affect the component itself, and any of its subcomponents. Component styles don’t affect anything external to them, nor any other components that might be nested within them. Take Brad Frost’s Atomic Design, where atoms combine to form molecules, which in turn combine to form organisms. To us at Mobify, Brad’s atoms, molecules and organisms are all components.

Atomic Design: Components may be combinations of subcomponents, but they are isolated to their own miniature ecosystem — nothing within a component will affect what is outside of its outer boundary.

CSM is a great methodology, and it serves us well — designers, user interface developers, and front-end engineers here all understand it. But on its own, the CSM naming convention presents issues when it comes to bloat, specifically around reusability. It’s a terrific solution if every component is exactly the same, but that’s hardly the case. It is often necessary to swap out different spacing values, perhaps different background colours, maybe change font sizes depending on the context.

Consider the following c-card component as an example:

What if we wanted that card to have a large padding value in a specific instance? We might consider using a modifier to be used in that scenario, such as:

Now consider we had a different component, c-hero

…and we also wanted to add a large amount of margining to the top? CSM notes that we should add yet another modifier here, thereby duplicating a line in CSS. While it might be perfectly acceptable to repeat one declaration here, these can quickly add up across and within components, leading to a surplus of rules that perform exactly the same task. It’s redundant, and it bloats our CSS.

Instead, we switched over to using more of a functional CSS approach — not entirely, but close. We use the functional CSS approach by treating utility classes as the bread and butter of how we layout elements.

Utility classes are simple, composable, and as reusable as possible. On their usage, front-end developer David Clark notes:

“They must be strictly categorized and tightly focused, or they lose their … utility — their raison d’être. They must epitomize the single responsibility principle. Unlike a component class a utility class could show up anywhere, on any element, in any context, so we need to know that it will always do exactly the same thing.”

Daniel Eden calls this approach “subatomic design.”

You then create components by composing subatomic components (properties). Rather than creating a component and its variants, you simply have a comprehensive list of “ingredient” subatomic components. Those subatomic components can be combined in thousands of ways to create hundreds of components. The properties of those components are numerous, but constrained to a set of acceptable values (our subatomic components).”

Subatomic design bypasses the creation of new classes and styles. Instead, we implement design patterns composed of existing classes. Once your baseline utility classes have been writing, there’s no need to write new CSS. With these creating small, single-purpose classes that can be ported and applied anywhere, we can then limit component styles to predominantly non-variant styles. After removing the margin values from our components and using utilities as the “wiggle” states for elements, we end up with class chains looking a little like this:

Having to write and rewrite utilities over and over again can be a bit unruly, but it’s a much better solution then having 12.3k — ahem — declarations of exactly the same code.

“But Ben, isn’t it a tradeoff from CSS to HTML, where you are overloading elements with classes?” Well, yes. But — and it’s a big but — if it reduces the size of the stylesheet resource, it’s a major win for shoppers. I follow David Clark’s sentiment on the matter:

When it comes to code, however, as with design, my priorities are placed first and foremost on the end user. If I can shave even 10 kilobytes of code from a user’s mobile data consumption, or several hundred milliseconds off the time it takes them to access the products I work on, I’m going to do it … If that means I need to work harder to create a shared understanding for those who design and develop alongside me, that’s fine.

But it’s also a big improvement for maintenance. Need to adjust a specific text size? No problem, just swap a single class. Margining? Same. With more emphasis on utilities, the majority of maintenance and modification happens in the class attribute instead of in stylesheets.

Using more utilities over components also allows other non-developers easily make adjustments on the fly (like designers changing things in-build). Our front-end engineers, who are primarily focused on data parsing, can also drop in classes and drop in some rudimentary styling without having a deep knowledge of a component’s visual system.

While we reducing stylesheets with naming conventions, this ultimately began with the creation of the design system. By limiting element variations in our design system from the get-go (particularly around colour, font size, and layout) and using utilities for the variations that do occur, we were able to cut down our stylesheet by 86% — down to just 83 kb. notbad.jpg

When removing bloat from your own stylesheets, think of the following:

  • limit colour, font, and size variations
  • write and use reusable code first
  • treat CSS as subatomic design

Reducing Asset Bloat

The second area of bloat came from assets: images, primarily. There were 42 images on the desktop home page experience that actually showed (almost 3 Mb worth) with another 23 in the DOM but not displayed (almost 1.5 Mb). Did all of those images really create an optimal experience? Would bringing those through to the mobile experience have a positive effect on the shopper?

Of course not. 🙅🏽

I started thinking about the One Less JPG solution, here. It has been around for a near half-decade at this point, and it’s an interesting thought experiment. The idea is that after your design is completed, go ahead and remove one image, since an image potentially has the same weight as a JS library, which are often bloated in themselves.

Of course, browsers handle images differently than Javascript. (JS obviously has a larger parsing impact on browsers, and requires more to execute than downloading and displaying a bitmap asset.) But what I like about One Less JPG is that it forces you to reconsider what you really need. To me, One Less JPG is really One Less Everything: What is crucial to the user in this instance? What actions will they take? How are we facilitating those interactions?

It’s thinking about what can be removed from your design so that the shopper can efficiently prioritize digesting or acting.

We cut out as much decorative imagery wherever we could. Where we did need images, I tried changing it over to a CSS implementation if possible. Icons were all created as SVGs and served in an SVG spritesheet. And any bitmap image that needed to be included as-is was rigorously crunched and optimized with reduction tools.

In other words, our new One Less Everything method is really about content overcoming laziness — making conscious decisions about the intent you wish to convey.

When removing bloat from your own assets, think of the following:

  • Consider if you really need that image.
  • Consider building that image out of CSS instead.
  • Consider serving that image on a delay (e.g. lazy loading).
  • Optimize images for the web.

The most performant site is one weighing 0 kb — we could work all day and cut, reduce, and remove content from our site until there was nothing left. But that’s obviously ridiculous.

Finding a balance between a fast experience and one with the right look and feel is crucial. Sacrifices will have to be made in both directions.

The solution is acute awareness and vigorous testing.

Let’s stop being lazy, and consider every decision put into a project. Weigh the pros and cons. Make a decision, form a plan, do whatever it takes to provide users an excellent experience. Then test the implementation with real users, see if it works, and then act on the results. For me as a designer, that meant:

  • Starting with a small, uncomplicated design system that scaled up without much variance,
  • Keeping design documentation up-to-date, and collaborating with developers to implement components properly,
  • Checking the page weight and critical path often using browser plug-ins and weight and speed tools.

Being a designer here means taking ownership of a project from start to finish. It means examining the shopper’s needs from every angle and boiling complex problems down to streamlined and highly functional interfaces. We follow a set of five principles to ensure we are creating products that are exceptionally crafted, solve real user problems, and give us business insights along the way: Be Human, Communicate Clearly, Deliver Value, Keep It Simple, and Exhibit Craftsmanship. (Read more about our principles in Jordan Girman’s article Creating Design Principles.) Designing for performance is a concept that falls into every category of our principles. Speedy performance means:

  • Creating solutions that are tailor-made to suit real user needs,
  • Making sure our products are clearly communicating to the shopper in exactly the right and efficient way,
  • Delivering value on an ongoing dialogue between stakeholders, and compromising wherever we can in favour of the shopper,
  • Striving to execute usable, elegant designs with simple layouts and interactions benefiting both the business and the shoppers,
  • Creating work that is lovingly crafted, built with care and passion, and presented with pride.

It’s a no-brainer to us that our Progressive Mobile web apps and native apps should be designed with performance in mind; by incorporating performance considerations into the design process right from the get-go, we can ensure shoppers have fast mobile experiences.

Hi there, I’m Ben, a designer and front-end developer in Vancouver, Canada. We should chat: leave a comment here or get at me on Twitter. (Note: this article was originally published as “Designing Mobile Commerce Sites for Performance” on Mobify Insights.)✌🏼

--

--