One of the critical phases of building a web app is diagnosing performance issues, in this blog, we'll discuss the different tools and tricks that we use to keep our web apps as lean and fast as possible.

know your dependencies

it can be overwhelming how much libraries are published to npm every day, and most of the time adding a feature could be nothing more than an npm install and few lines of configuration that's why you'd end up with a fat bundle more often than you'd like.

source-map-explorer

source-map-explorer is a tool that shows you a treemap visualization to help you debug where all the code is coming from.

Install:

npm install -g source-map-explorer  

Usage:

source-map-explorer bundle.min.js  
source-map-explorer bundle.min.js bundle.min.js.map  

source-map-explorer generates an HTML file that you can interact with
Lighthouse audits

Webpack Analyzer

Webpack Analyzer is a website that takes in a webpack-stats.json and draws a tree that represents how your dependencies are linked together

Usage:

webpack --profile --json > webpack-stats.json  

Lighthouse

Lighthouse started as a chrome extension and was added to DevTools since Chrome 60, it's an automated tool for improving the quality of web pages. You can run it against any web page, public or requiring authentication. It has audits for performance, accessibility, progressive web apps, and more.

Usage:

  1. Open DevTools
  2. Click the Audits tab
  3. Click Perform an audit..

the result would look like this:
Lighthouse audits Lighthouse audits

why-did-you-update

Why did you update is a function that monkey patches React and notifies you in the console when potentially unnecessary re-renders occur.

Usage:

import React from 'react'

if (process.env.NODE_ENV !== 'production') {  
  const {whyDidYouUpdate} = require('why-did-you-update')
  whyDidYouUpdate(React)
}

Code-Splitting

Most React apps will have their files “bundled” using tools like Webpack or Browserify. Bundling is the process of following imported files and merging them into a single file: a “bundle”. This bundle can then be included on a webpage to load an entire app at once.

Bundling your code in one file is good, but as your code grows the longer the first render would take, Code-splitting your app can help you “lazy-load” just the things that are currently needed by the user

using import()

one of the ways to introduce code-splitting into your app is through the dynamic import()

Before

import { add } from './math'

console.log(add(16, 26))  

After

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

using react-loadable

react-loadable is a higher order component for loading components with promises.

Before:

import OtherComponent from './OtherComponent'

const MyComponent = () => (  
  <OtherComponent/>
)

After:

import Loadable from 'react-loadable'

const LoadableOtherComponent = Loadable({  
  loader: () => import('./OtherComponent'),
  loading: () => <div>Loading...</div>,
})

const MyComponent = () => (  
  <LoadableOtherComponent/>
)