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

How To Stay Productive When Dealing With Anxiety Disorder

Disclaimer: This isn't really a hack. There are no eight steps to beat any kind of disorder. If you'...

8_January_2020

Setting Expectations for Software Engineering Teams

Introduction When I started at Andela as CTO I had an opportunity to introduce myself and set expec...

19_December_2019

Battle-tested hacks to grow exponentially as a software engineer

So, you just switched careers and now you are into tech, a software engineer or you have been doing ...

9_December_2019

Remote Heroes Kampala: Event Recap

The Remote Heroes event in Kampala was held on 21st November 2019 at Innovation Village in Ntinda. G...

29_November_2019

Democratising Access To Smart Freighting

Catherine Kimani is a software engineer at Andela Kenya. Over the last 7 months, while living in Nai...

27_November_2019

Javascript convert to boolean using !!(double bang)operator

Every value has an associated boolean, true or false, value in JS. For example, a null value has an ...

21_November_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.