This post is meant to sensitize us on the importance of the performance of our web apps. If you are like me, when you started in software development, your initial concern was getting your code to run and for the application to go live. Later, you start to grapple with delivering the best user experience to users. This then leads you to start thinking of performance.

In this article, I attempt to share how to measure the performance of our application using an open-source tool known as Lighthouse. There are other tools in the market but this one is easily accessible as it ships with the Chrome browser. I will also share some practices that can help you improve the performance of your app. I will also attempt to explain some technical concepts that will be useful to us as developers.

What exactly is web performance?

The honest truth is that web performance is both subjective and objective. As a user, it is subjective. From a user’s point of view, web performance is about how fast a user perceives the site to be. That is, the user’s perception of whether the time it takes between the time s/he requests the content and the time until s/he feels the content requested is available and usable feels slow or fast.

Objectively, it is the measurable time, in milliseconds, it takes for the web page or web application to be downloaded, painted in the user’s web browser, and become responsive and interactive. That is, the objective time of when a request for content is made until the requested content is displayed on the user’s browser.

What is web performance optimization?

Web performance optimization is simply all the steps you will take as a developer to increase the subjective and objective web performance.

Why are we discussing performance and optimization?

It is important to discuss performance and optimization because of how fast or slow our app impacts our end users. And as developers, we are solving problems for our users. If we are not able to satisfy our users, we will lose money and product would suffer.

It is also important to factor in performance during development because our app will be used under different network conditions and on different devices with different capabilities.

Take a look at this 2017 study showing how long it took different mobile phones to parse 1MB of Javascript:

The cost of parsing 1MB of Javascript by various mobile devices.

This data shows us that there is a 2–5x difference in time to parse/compile code between the fastest phones on the market and average phones. This implies that while you develop with fast 4G on your MacBook or DellInspiro, your user might use your app on a 3G network with a device with a slow GPU. How do you accommodate that? That’s why you need to factor in performance while developing your apps.

How do we measure performance?

In order to develop with performance in mind, we need to be able to measure performance. How do we do that?

We can use tools such LightHouse, GTMetrix.comWebPageTestPageSpeedInsights. In this article, I will be using Lighthouse.

Measuring Performance

To show you how lighthouse works, I will demo it with a personal project. This app is live here: https://sammie-fast-food-fast-react.herokuapp.com/

Follow the following steps:

1. Launch a new Chrome tab in Incognito mode (Control+Shift+N). This is so that your chrome extensions (if you have any) do not interfere with the audits.

2. Type https://sammie-fast-food-fast-react.herokuapp.com/ (or any app whose performance you want to measure) into the address bar and open up the Chrome developer tools using either of these commands: Command+Option+I (Mac) or Control+Shift+I (Windows, Linux).

3. You can open the developer tools section to the right as shown in the image below for convenience.

4. Switch over to the Audits tab. The Audits tab uses LightHouse. So with this, we will measure the performance of the app. Lighthouse will also provide insights on how we can improve performance.

Image showing the audits tab in Chrome Dev Tools

For this audit, you can configure Lighthouse however you wish. In this instance, we want to audit the site for performance on a mobile device. We also want to simulate a slow 4G network and 4x CPU slowdown( That is, your current device performance slowed down by a factor of 4).

To run the audit, click on the Run audits button.

Below is the result of running the audits:

The result of the audit on https://sammie-fast-food-fast-react.herokuapp.com

This audit scores the performance of the app at 57%. However, there are important metrics that Lighthouse exposes to us.

Important metrics of web performance

These metrics shown above are used to specifically measure how performant our app is. You can click on the learn more link on each to read more on each metric(I would not want to do that in this article so this doesn’t get too long).

By using the Audits Tab, we can know how performant our app is.

So how do we optimize the performance?

We can optimize the performance of our app at load time or runtime. In this article, I will be looking at load time.

As a developer, what I can do now to improve performance?

Write mobile-first CSS

  • This will give the browsers of smaller devices less work to do as the browser only needs to the calculations for their screen sizes.

Code Splitting.

  • Today, most web applications are built using frameworks/libraries such as React, Vue, Angular, etc. These libraries use tools such as Webpack or Browserify to bundle your application code. Bundling is simply the process of following imported files and merging them into a single file: a “bundle”. The idea of code splitting is to serve only the code needed for the routes or components or user actions that a user requests for per time(lazy loading) instead of serving all the application code at the same time. (eager loading).
  • How do you implement code splitting?/Code Splitting in details

Code splitting is done using dynamic imports using the dynamic import() syntax. Note that the import() syntax is an ECMAScript (JavaScript) proposal not currently part of the language standard. It is expected to be accepted in the near future.

Here is a simple example of the use of the dynamic imports syntax taken from the React documentation:

Before:

import {add} from ‘./math’console.log(add(2,2))
With import() syntax, this becomes:

import("./math").then(math => {
  console.log(math.add(2, 2));
});


Note that import() calls use promises internally. So, if you use import() with older browsers, remember to shim Promise using a polyfill such as es6-promise or promise-polyfill.

How then do you introduce code splitting into your app?

You can split the code for your app based on the routes. That is, you want to load the code for a route only when it is needed.

Below is a route based code splitting implementation from the React documentation using libraries like React Router with the React.lazy function.

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

You can also implement something similar in Vue.js using the Vue-router. Below is an example of Vue-Router code implementing code splitting on the basis of the routes

{path: '/publications',name: 'AllPublications',component: () => import('@/pages/Publications/AllPublications'),meta: { isAuth: true  }},

So, what the above means, is that the code the publications page will only be loaded when the user navigates to the route, ‘/publications’Until the user navigates to this route, the code for the publications page is not loaded onto the browser.

Something similar is done in Angular’s routing as well. Below is an example from the Angular documentation:

const routes: Routes = [
{
  path: ‘customers’,
loadChildren: () =>  import(‘./customers/customers.module’).then(mod => mod.CustomersModule)
},
{
 path: ‘orders’,
loadChildren: () => import(‘./orders/orders.module’).then(mod => mod.OrdersModule)
},
{
 path: ‘’,
 redirectTo: ‘’,
 pathMatch: ‘full’
}];

In summary, when you code split based on routes, you serve only the chunks your users need per route.

See more on code splitting/Lazy loading in React here.

See more on code splitting/Lazy loading in Vue here.

See more on code splitting/Lazy loading in Angular here.


That’s quite a lot to take in.

So, now that we have looked at some code, what factors do we know that can affect the performance of our apps.

  • Network Conditions
  • Device GPU of users.

Conclusion

The performance of our apps would always have a subjective feel to it. This is because it is an experience that no one metric can fully capture. There are multiple moments during the load experience that can affect whether a user perceives it as “fast” or “slow.”

In testing, we must pay attention to the little wins that cumulatively increase application speed and result in a better experience for the end-user.

featured_image
About the Author

Samuel Adeniran

Software Engineer @ Andela

Thanks for subscribing!

 

More Insights

July 19, 2019

Measuring and Optimizing Web Performance

Samuel Adeniran

This post is meant to sensitize us on the importance of the performance of our web apps. If you are like me, when you started in software development, your initial concern was getting your code to run and for the application to go live. Later, you start to grapple with delivering the best user experience to users. This then leads you to start thinking of performance.

In this article, I attempt to share how to measure the performance of our application using an open-source tool known as Lighthouse. There are other tools in the market but this one is easily accessible as it ships with the Chrome browser. I will also share some practices that can help you improve the performance of your app. I will also attempt to explain some technical concepts that will be useful to us as developers.

What exactly is web performance?

The honest truth is that web performance is both subjective and objective. As a user, it is subjective. From a user’s point of view, web performance is about how fast a user perceives the site to be. That is, the user’s perception of whether the time it takes between the time s/he requests the content and the time until s/he feels the content requested is available and usable feels slow or fast.

Objectively, it is the measurable time, in milliseconds, it takes for the web page or web application to be downloaded, painted in the user’s web browser, and become responsive and interactive. That is, the objective time of when a request for content is made until the requested content is displayed on the user’s browser.

What is web performance optimization?

Web performance optimization is simply all the steps you will take as a developer to increase the subjective and objective web performance.

Why are we discussing performance and optimization?

It is important to discuss performance and optimization because of how fast or slow our app impacts our end users. And as developers, we are solving problems for our users. If we are not able to satisfy our users, we will lose money and product would suffer.

It is also important to factor in performance during development because our app will be used under different network conditions and on different devices with different capabilities.

Take a look at this 2017 study showing how long it took different mobile phones to parse 1MB of Javascript:

The cost of parsing 1MB of Javascript by various mobile devices.

This data shows us that there is a 2–5x difference in time to parse/compile code between the fastest phones on the market and average phones. This implies that while you develop with fast 4G on your MacBook or DellInspiro, your user might use your app on a 3G network with a device with a slow GPU. How do you accommodate that? That’s why you need to factor in performance while developing your apps.

How do we measure performance?

In order to develop with performance in mind, we need to be able to measure performance. How do we do that?

We can use tools such LightHouse, GTMetrix.comWebPageTestPageSpeedInsights. In this article, I will be using Lighthouse.

Measuring Performance

To show you how lighthouse works, I will demo it with a personal project. This app is live here: https://sammie-fast-food-fast-react.herokuapp.com/

Follow the following steps:

1. Launch a new Chrome tab in Incognito mode (Control+Shift+N). This is so that your chrome extensions (if you have any) do not interfere with the audits.

2. Type https://sammie-fast-food-fast-react.herokuapp.com/ (or any app whose performance you want to measure) into the address bar and open up the Chrome developer tools using either of these commands: Command+Option+I (Mac) or Control+Shift+I (Windows, Linux).

3. You can open the developer tools section to the right as shown in the image below for convenience.

4. Switch over to the Audits tab. The Audits tab uses LightHouse. So with this, we will measure the performance of the app. Lighthouse will also provide insights on how we can improve performance.

Image showing the audits tab in Chrome Dev Tools

For this audit, you can configure Lighthouse however you wish. In this instance, we want to audit the site for performance on a mobile device. We also want to simulate a slow 4G network and 4x CPU slowdown( That is, your current device performance slowed down by a factor of 4).

To run the audit, click on the Run audits button.

Below is the result of running the audits:

The result of the audit on https://sammie-fast-food-fast-react.herokuapp.com

This audit scores the performance of the app at 57%. However, there are important metrics that Lighthouse exposes to us.

Important metrics of web performance

These metrics shown above are used to specifically measure how performant our app is. You can click on the learn more link on each to read more on each metric(I would not want to do that in this article so this doesn’t get too long).

By using the Audits Tab, we can know how performant our app is.

So how do we optimize the performance?

We can optimize the performance of our app at load time or runtime. In this article, I will be looking at load time.

As a developer, what I can do now to improve performance?

Write mobile-first CSS

  • This will give the browsers of smaller devices less work to do as the browser only needs to the calculations for their screen sizes.

Code Splitting.

  • Today, most web applications are built using frameworks/libraries such as React, Vue, Angular, etc. These libraries use tools such as Webpack or Browserify to bundle your application code. Bundling is simply the process of following imported files and merging them into a single file: a “bundle”. The idea of code splitting is to serve only the code needed for the routes or components or user actions that a user requests for per time(lazy loading) instead of serving all the application code at the same time. (eager loading).
  • How do you implement code splitting?/Code Splitting in details

Code splitting is done using dynamic imports using the dynamic import() syntax. Note that the import() syntax is an ECMAScript (JavaScript) proposal not currently part of the language standard. It is expected to be accepted in the near future.

Here is a simple example of the use of the dynamic imports syntax taken from the React documentation:

Before:

import {add} from ‘./math’console.log(add(2,2))
With import() syntax, this becomes:

import("./math").then(math => {
  console.log(math.add(2, 2));
});


Note that import() calls use promises internally. So, if you use import() with older browsers, remember to shim Promise using a polyfill such as es6-promise or promise-polyfill.

How then do you introduce code splitting into your app?

You can split the code for your app based on the routes. That is, you want to load the code for a route only when it is needed.

Below is a route based code splitting implementation from the React documentation using libraries like React Router with the React.lazy function.

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

You can also implement something similar in Vue.js using the Vue-router. Below is an example of Vue-Router code implementing code splitting on the basis of the routes

{path: '/publications',name: 'AllPublications',component: () => import('@/pages/Publications/AllPublications'),meta: { isAuth: true  }},

So, what the above means, is that the code the publications page will only be loaded when the user navigates to the route, ‘/publications’Until the user navigates to this route, the code for the publications page is not loaded onto the browser.

Something similar is done in Angular’s routing as well. Below is an example from the Angular documentation:

const routes: Routes = [
{
  path: ‘customers’,
loadChildren: () =>  import(‘./customers/customers.module’).then(mod => mod.CustomersModule)
},
{
 path: ‘orders’,
loadChildren: () => import(‘./orders/orders.module’).then(mod => mod.OrdersModule)
},
{
 path: ‘’,
 redirectTo: ‘’,
 pathMatch: ‘full’
}];

In summary, when you code split based on routes, you serve only the chunks your users need per route.

See more on code splitting/Lazy loading in React here.

See more on code splitting/Lazy loading in Vue here.

See more on code splitting/Lazy loading in Angular here.


That’s quite a lot to take in.

So, now that we have looked at some code, what factors do we know that can affect the performance of our apps.

  • Network Conditions
  • Device GPU of users.

Conclusion

The performance of our apps would always have a subjective feel to it. This is because it is an experience that no one metric can fully capture. There are multiple moments during the load experience that can affect whether a user perceives it as “fast” or “slow.”

In testing, we must pay attention to the little wins that cumulatively increase application speed and result in a better experience for the end-user.

featured_image
About the Author

Samuel Adeniran

Software Engineer @ Andela

Thanks for subscribing!

 

More Insights

Evolving HR Through Design Thinking

Growing up as a child, a lot of things intrigued me. Top on the list was food, my special stones (ak...

23_August_2019

Finding Answers: Benedicte Musabimana’s Dev Journey

"When I was a kid, I always wanted to know how a computer or a mobile phone worked." Benedicte is...

21_August_2019

Introducing The Andela Talent Marketplace

Andela set out as a company to advance human potential by investing heavily in building technology l...

20_August_2019

On Designing Good Microservices Architectures

It may be difficult to know exactly what constitutes a well-designed microservice on your first assi...

19_August_2019

RubyConf Kenya 2019: My Nairuby Recap

Two weeks ago was the first time I attended a Ruby conference outside my home country, and boy was i...

14_August_2019

How To Manage Communication as a Distributed Product Manager

With more companies embracing distributed and remote work teams, the communication challenge tak...

9_August_2019

Partners

Tap into a global talent pool and hire the “right” developers in days, not months.

Developers

Accelerate your career by working with high-performing engineering teams around the world.

BECOME A DEVELOPER

Hire Developers

We take great pride in matching our developers with the best partners. Tell us about your team below!

preloader_image

Thank you for your interest

A member of our team will reach out to you soon.