My Experience With Progressive Web Apps

Progressive Web Apps is a paradigm to make webapp more efficient on mobile devices. They are the future.

I built a Progress Web App of WhatsApp Web using Webpack 2.0, React and Express.

Note: This is not a complete clone of WhatsApp Web but minimal one to have an understanding of how to create a PWA app.

Case Study

Main aim of PWA apps should be making the load time of webapp faster.

Server Side Rending

Server Side Rendering (App shell architecture) is a way of making the load time faster without JavaScript . Initially we can render a simple HTML, CSS as string from the server. Once the DOM is loaded JS will take over the website (Isomorphic more precisely).

Sample Code of match api from react-router

Bundling

Various ways are available to bundle the app with minimum size using Webpack.

I say separating the vendor libraries and components is the best way to reduce the bundling size. Vendor can be browser cached and can be served for multiple request and app components can be attached with build id as app.12312.js to serve as new file for every requests.

Webpack’s commonChunksPlugin can be used to create a common chunk as separate bundle from source code.

Gzip all the resources used on the webApp using CompressionPlugin.

Use Preact instead of React to further reduce bundled size. Add the following lines of code in webpack.config.js to use React.

resolve: {
alias: {
react: 'preact-compat',
react-dom: 'preact-compat'
}
}

Plugins like AggressiveMergingPlugin, OccurrenceOrderPlugin are also used to reduce the bundle size.

Code Splitting

Web pack 2.0 provides a nice way to do the code splitting.

System.resolve is the way to split the code. Webpack reads for it and creates separate bundles.

if (this.props.routeName !== nextProps) {
if (routeName === 2) {
System.import('./Messages').then(Component => {
this.messageComponent = Component.default;
this.forceUpdate();
});
}
if (routeName === 3) {
System.import('./Details').then(Component => {
this.detailsComponent = Component.default;
this.forceUpdate();
});
}
}

You can see how I have done that for two components which results as below.

Various bundles based on bundling

If you examine the above picture Webpack have created four bundles (app.js, bundle.vendor.js, bundle.0.js and bundle.1.js).

This is because I have separated the app.js for components and vendor.js for Vendor libraries. The remaining two bundles are precisely due to code splitting.

react-router can be used for Route based splitting out of box with Webpack

Workers From Web

Web workers and Service workers are most useful feature from web. Both the workers have no access to DOM.

Web Workers are use to do heavy operation in separate thread of browser and return result to the web app.

Service workers are useful for caching the request. It acts as an intermediate for every request and caches it. If the same request is made again it responds from SW. Once the responses have arrived from the server, Service Workers replace the particular response from cache. Service Workers are useful receiving Push and doing background sync

Simple Service Worker configuration
Same Response from the Service Worker

More Techniques

  • Webpack 2.0 uses treeShaking feature which is use for leaving the un- imported code from bundles.
  • Use pre-cache (resource need urgently), pre-fetch(resource may be needed in feature) and defer. All three attributes are used for loading the scripting without blocking onLoad function.
  • Use Web manifest.json to have Native feel when users does Add to Home Screen in Mobile.
  • Use LightHouse Chrome extension to validate your website

Useful Articles

  1. Progressive web app with with React.js — Four parts
  2. preload-prefetch-and-priorities-in-chrome
  3. Twitter Lite
  4. Uber Clone
  5. Prefer defer over Async
  6. Getting most out of CommonChunksPlugin
  7. Vendor and Code Splitting in Webpack
  8. Useful webpack plugins
  9. The Offline Cookbook
  10. Http Browser Caching