Tajawal and Almosafer Progressive Web App

khurrum qureshi
Published in
5 min readMay 26, 2018


We are glad to announce that we have recently launched new mobile web experience for Tajawal and Almosafer which is a Progressive Web App. It is designed by employing techniques for JavaScript performance optimization, Service Workers for network resilience and best architectural practices. Let’s take a look at our learnings during this journey.

Journey to a Progressive Web App

Our objective is to provide our users a delightful user experience which is performant enough where they can get through the flight booking process within one minute. On the other hand, we wanted to build something which is scalable, maintainable and reusable.

The MVP for the PWA took 2 months to implement using React as the UI library and we build our core in native javascript.


We launched our tajawal and almosafer web apps back in 2015. We built our architecture using AngularJS which was one of the best available option at that time to build an enterprise level web application. It worked quite well for us and we are using it for our desktop web to-date. However, as we all know that AngularJS has some issues and one of the prominent one is performance which is why Google relaunched it as Angular after a complete revamp.

Furthermore, when we decided to move away from AngularJS it was the time when we realized that our architecture is quite tightly coupled with the framework. Hence, we needed to rebuild everything from scratch in order to get away from AngularJS.

As an enterprise the decision was challenging yet practical. So, we decided to build our architecture from scratch.We designed an architecture which is easy to scale, can be reused, easy to maintain in long-term and fulfill all our specific requirements, which include:

  • It must provide us an easier way to maintain multiple sites (Tajawal and Almosafer) within a same codebase.
  • We must be able to provide completely separate user journey for both desktop and mobile users.
  • It should be multi-lingual.
  • It should be framework independent as much as possible.
  • It should be flexible to adopt any upcoming changes in future and we should not have to rebuild everything from scratch again.

Based on our requirements, we came up with a multi-layer architecture which consists of two main layers UI layer and Business layer. UI layer is built using ReactJS and Business layer is built using native javascript.

We only keep UI components, navigation and some basic UI related logic in UI layer. UI layer also has a modular structure which supports separate UI journeys for mobile and desktop. We are using webpack for bundling the app which allows us to create separate builds for mobile and desktop.

Our business layer consists of different sdks which contain our core business stuff like http services, models, data transformation, storage service etc. We are using mono repo to maintain all our sdks.

This architecture is flexible as most of the code base is in native javascript. Hence, we can easily replace our UI layer with any other library with minimal effort in future. Moreover, it can scale as it supports multi-platform and multi-site also it is easily reusable if we need to implement flight or hotel booking flows in different systems we can easily implement it.


The mobile devices Tajawal and Almosafer Online’s users most commonly access their web experience with include:

  • Apple iPhone
  • Samsung Galaxy S8
  • Samsung Galaxy S7

Testing the new experience on Lighthouse (using the 3G) we can see that they’re able to load and get interactive in under 3.6 seconds:

Tajawal Mobile Web Performance
Almosafer Mobile Web Performance

Performance Optimization

We were able to improve how quickly pages could load and become interactive through a number of techniques. We implemented route-based code-splitting, introduced performance budgets and long-term asset caching.

Route-level code-splitting

We initially had large, monolithic JavaScript bundles that delayed how quickly our experience could get interactive. These bundles contained code that wasn’t immediately needed to boot-up the core user experience, so it could be broken up using code-splitting. It’s generally useful to only ship code users need upfront and lazy-load the rest as needed.

To accomplish this, We used React Router and React Loadable. As our application centralized all their route and rendering info a configuration base, we found it straightforward to implement code splitting at the top level.

For “vendor” (library) chunking, we used the webpack CommonsChunkPlugin to move commonly used libraries across routes up to a single bundle file that could be cached for longer periods of time.


After introducing route-based code-splitting our main bundle sizes went down from 150KB to 21KB and First Interactive Time improved from 13.52s to 3.58s.

Preloading late-discovered resources

We implemented support for to preload our critical JavaScript/webpack bundles and fonts that were important for the core experience.

Performance budgets

To get and stay interactive quickly, We enforced a budget of ~150KB for our main and vendor chunks. This was crucial to ensuring we were able to avoid regressing on performance.

CSS Strategy

We are using Material UI to create highly reusable UI. We are using JSS to define CSS within components. It helps us to keep CSS scope limited to specific components. We don’t have any CSS bundles in our application all the CSS has been injected inline at runtime.

Workbox for network resilience and offline asset caching

We use the Workbox Webpack plugin for caching our core static assets like main, vendor and manifest bundles. This enables network resilience for repeat visits and ensures that the application starts-up more quickly when a user returns for subsequent visits.

We also implemented offline experience so, the user can still access some of the app features while offline.


Consequently, our next big launch will be hotels which is going to be launched within next three months. We will continue improving our application performance and features. We have already started seeing the results in terms of improved conversion rate which is increased by 2X. Stay tuned for more progress in the near future!

With thanks to Muhammad Talal, Muhammad Ahmed, Ahmed Abdalla, Arif Masood, Yusuf Algan for making this happen.



khurrum qureshi

Web at @tajawal #javascript #nodejs #webperformance #pwa #reactjs