Powering a Web App: 2 Assets React.js and PWA

Powering a Progressive Web App (PWA) with React.js can bring several benefits and advantages to the development process.

Next you’ll find reasons why React.js is commonly used to build PWAs: Component-Based Architecture, Virtual DOM, React Router among others!

A Progressive Web App [PWA]

A progressive web app leverages modern web technologies to provide a UX similar to that of native mobile applications. PWAs are designed for a diversity of platforms and devices, like: desktops, smartphones, and tablets.

Here are some key features of progressive web apps:

  1. Progressive Enhancement: PWAs are built with progressive enhancement in mind, they are designed to work on any device, regardless of the browser or platform limitations. They are accessed by/with modern browsers that support service workers.
  2. Responsive: PWAs are responsive and adapt to different screen sizes and orientations, providing a consistent experience across various devices.
  3. App-like Experience: PWAs aim to deliver an app-like experience to users, even when accessed through a web browser. They often have a full-screen mode, push notifications, and can be launched from the home screen.
  4. Offline Functionality: One of the significant advantages of PWAs is their ability to work offline or in areas with a weak or no internet connection. They can cache data and resources to ensure users can access content even without an active internet connection.
  5. Service Workers: PWAs utilize service workers, which are scripts that run in the background and enable features like offline caching, push notifications, and background synchronization.
  6. Secure: PWAs are served over HTTPS to ensure a secure connection between the user and the application, protecting against potential security threats.
  7. Discoverability: PWAs are easily discoverable as they can be indexed by search engines, making them searchable and shareable like traditional websites.

By combining the advantages of web technologies with the capabilities of native applications, PWAs provide an efficient and accessible way to deliver app-like experiences to users across various devices and platforms.

Find some examples here.

Why React.js for PWAs

React.js is a popular JavaScript library for building user interfaces, and it can be a great choice for developing Progressive Web Applications for several reasons:

  • Component-Based Architecture: it allows you to break down the UI into reusable and independent components. This modular approach makes it easier to manage and maintain your PWA codebase.
  • Virtual DOM: an abstraction of the actual DOM. React efficiently updates and renders the necessary components when there are changes, improving its performance.
  • Reusability and Code Sharing: you can build reusable components that can be used across multiple pages or views within your PWA. This reduces development time and effort, making it easier to maintain and update.
  • Large Ecosystem and Community: there are numerous libraries, tools, and resources available to help you build and enhance your PWA. You can find ready-made solutions.
  • Support for Server-Side Rendering (SSR): allows you to pre-render your application on the server and deliver a fully rendered page to the client. This improves the initial loading speed of your PWA and provides better SEO.

Even though React.js is not the only framework you can use for building PWAs, its component-based architecture, performance optimizations, code reusability, and vibrant ecosystem make it a popular choice.

So, what is a Progressive Web App?

Here we have some progressive web app examples for you to get it from real life samples:

First we have Twitter that offers a PWA called Twitter Lite, providing a lightweight version of the Twitter experience.

It offers offline support, push notifications, and a responsive design, allowing users to browse and engage with tweets even in low network conditions.

Starbucks developed a PWA that allows customers to browse their menu, customize orders, and find nearby stores.

The PWA utilizes geolocation, offers offline support, and can be added to the home screen for quick access.

We can also find Pinterest, which has a PWA that provides a fast and responsive experience for browsing and saving pins.

It includes features like push notifications, offline access, and the ability to save the app to the home screen.

A common app among Gen Xs: Flipboard, a popular news and content aggregation platform, offers a PWA that provides a magazine-style layout and offline reading capabilities.

Users can customize their news feed, save articles for later, and enjoy a seamless experience across devices.

Known commuting service; Uber has a PWA that allows users to book rides, track drivers, and manage their accounts.

The PWA leverages location services, push notifications, and caching to provide a reliable and app-like experience.

And for those with an itchy feet: Trivago, a hotel search and booking platform, offers a PWA that enables users to search for hotels, compare prices, and make reservations.

It provides a responsive design, offline support, and can be installed as an app on mobile devices.

These examples demonstrate how PWAs can provide a native-like experience, including features such as offline access, push notifications, and device integration, while being delivered through the web and accessible across different devices and platforms.

Some Code Samples Taking Uber As A Case Study

We don’t have access to Uber’s specific codebase, but we can provide a simplified code example to illustrate how Uber could use a PWA architecture.

Keep in mind that this is a general example and not an exact representation of Uber’s implementation.

Service Worker Registration:

To enable offline support and caching, Uber would typically register a service worker in the client-side JavaScript code. The service worker intercepts network requests and allows for caching and handling of offline scenarios.

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
      .then(registration => {
        console.log('Service Worker registered:', registration);
      })
      .catch(error => {
        console.log('Service Worker registration failed:', error);
      });
  });
}

Caching Strategies:

Uber would define caching strategies within the service worker to determine which resources to cache and how to handle network requests.

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('uber-cache').then(cache => {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/app.js',
        '/images/logo.png',
        // additional resources to cache
      ]);
    })
  );
});


self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

Web App Manifest:

Uber would provide a web app manifest file, which defines metadata about the PWA, such as the app’s name, icons, colors, and display preferences.

{
  "name": "Uber",
  "short_name": "Uber",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#fff",
  "theme_color": "#000",
  "icons": [
    {
      "src": "/images/icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ]
}

Push Notifications:

Uber might implement push notifications to send real-time updates to users. This involves requesting permission from the user and registering a push service worker.

// User permission request
Notification.requestPermission().then(permission => {
  if (permission === 'granted') {
    // Register a push service worker
    navigator.serviceWorker.getRegistration().then(registration => {
      registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: 'your_public_key'
      }).then(subscription => {
        console.log('Push subscription:', subscription);
      }).catch(error => {
        console.log('Push subscription error:', error);
      });
    });
  }
});

These code snippets showcase some of the key elements and concepts that Uber (or any other application) could use in a PWA implementation.

PWAs differ from traditional web and native apps

PWA ⚛️

Category

Traditional/Native 📲

HTML, CSS, and JavaScript

Development Technologies

Platform-specific languages and frameworks.

→ iOS apps are usually developed in Swift or Objective-C.

→ Android apps are developed in Java or Kotlin.

PWAs are platform-agnostic and can run on any device with a modern web browser.

Platform Dependence

Built and optimized to run on a specific operating system. → iOS and Android require separate development efforts for each platform.

PWAs are distributed directly through the web. Users can access them by visiting a URL and optionally “install” them to their home screen for quick access.

Distribution

Platform-specific app stores like the Apple App Store or Google Play Store. Users must download and install them on their devices.

PWAs can offer offline functionality by caching necessary assets and data, allowing users to access certain parts of the app even without an internet connection.

Offline Functionality

Native apps often have more extensive offline capabilities since they can store larger amounts of data locally and have more control over device resources.

PWAs can access a subset of native features through web APIs, but their access may be limited or require additional permissions.

Access to Native Features

Native apps have direct access to a wide range of device-specific features and APIs, such as camera, contacts, sensors, and system-level functionalities. They can leverage these features to provide deep integration with the device’s hardware and operating system.

PWAs aim to provide a consistent user experience across platforms but may not fully match the look and feel of native apps. User Experience

Native apps can provide a highly optimized and tailored user experience specific to the platform they are developed for. They can take full advantage of platform-specific design guidelines, gestures, and interactions. 

An Introduction to React.js

If you have become a frequent reader of our blog posts, you should know by now that we’ve delve into react.js several times. Here we leave some links for you to access and dig in.

This post presents a react.js 101 guide for you to explore and learn, from rookie to senior, always helps! What’s react.js?

If you want to reinforce the reasons why react.js is an asset, click here!

Some fellow companies still wonder if using react.js or angular… but here, you’ll find a dynamic comparative chart that will help you consider the smartest choice.

And… if interested in contacting us to get your project done, schedule a meeting with our CEO ASAP!

Building a Progressive Web App with React.js

To build a Progressive Web App with React.js, you’ll need to follow a few steps. Here’s a high-level overview of the process, along with code examples for each step:

Set up a React.js Project:

Create a new React.js project using a tool like Create React App. Open your command line interface and run the following commands

npx create-react-app my-pwa
cd my-pwa

Register a Service Worker:

To enable offline support and caching, you’ll need to register a service worker in your React app.

Create a new file called service-worker.js in the public folder of your project with the following code:

// public/service-worker.js
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('my-pwa-cache').then(cache => {
      return cache.addAll([
        '/',
        '/index.html',
        // add additional static files to cache
      ]);
    })
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

Then, register the service worker in your index.js file:

// src/index.js
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
      .then(registration => {
        console.log('Service Worker registered:', registration);
      })
      .catch(error => {
        console.log('Service Worker registration failed:', error);
      });
  });
}

Create a Web App Manifest:

The web app manifest provides metadata about your PWA, such as its name, icons, and display preferences.

Create a manifest.json file in the public folder:

// public/manifest.json
{
  "name": "My PWA",
  "short_name": "My PWA",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#fff",
  "theme_color": "#000",
  "icons": [
    {
      "src": "logo.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ]
}

Include a reference to the manifest file in your index.html file:

<!-- public/index.html -->
<head>
  <!-- ... -->
  <link rel="manifest" href="/manifest.json" />
</head>

Optimize for Offline Support:

To improve offline capabilities, you can utilize libraries like Workbox. Install it by running the following command

npm install workbox-webpack-plugin --save-dev

Configure the Workbox plugin in your webpack.config.js file

// webpack.config.js
const { GenerateSW } = require('workbox-webpack-plugin');


module.exports = {
  // ... other config options ...
  plugins: [
    new GenerateSW()
  ]
};

Build and Deploy your PWA:

Build your React app and deploy it to a hosting provider of your choice. For example, using the following command:

npm run build

The generated build files can be hosted on a static hosting service like Netlify, Vercel, or GitHub Pages.

Quick reminder! This is a simplified example to help you get started with building a PWA using React.js.

In a real-world scenario, you may need to handle more advanced features like: push notifications, background sync, and responsive design based on your specific requirements.

Key Assets for Powering PWAs

When creating reusable and modular components in React.js for a Progressive Web App, it’s important to follow best practices to ensure maintainability and reusability.

Here are some guidelines to consider:

  1. Single Responsibility Principle: Each component should have a single responsibility, focusing on a specific task or feature.
  2. Component Composition: Leverage the power of component composition by breaking down complex UIs into smaller, reusable components.
  3. Prop Types and Default Props: to define the expected types of props passed to your components. Additionally, set default props to ensure that components can gracefully handle missing or undefined props.
  4. Reusable Styles: Separate your component styles into reusable and composable units using CSS modules, CSS-in-JS libraries, or preprocessors like Sass.
  5. Container and Presentational Components: Container components manage the state and business logic, while presentational components focus on rendering UI based on the props received.
  6. Controlled Components: Use controlled components, where the component’s state is controlled by props, rather than maintaining its own state.
  7. Context API: Utilize React’s Context API to share data and state between components that are not directly connected through props.
  8. Higher-Order Components (HOCs): HOCs allow you to wrap components with additional behavior, such as authentication or data fetching, without modifying the component itself.
  9. Testing: Write unit tests for your components to ensure their correctness and prevent regressions. Utilize testing frameworks like Jest and React Testing Library to create comprehensive test suites for your components.
  10. Documentation: Provide clear and comprehensive documentation for your reusable components, including their purpose, expected props, and usage examples.

By following these best practices, you can create reusable and modular components in React.js for your PWA, making your codebase more maintainable, scalable, and easier to work with.

Another asset: Service Workers. Implementing service workers for offline functionality and caching, you can find a hands on example in this subheading: Building a Progressive Web App with React.js.

Integrating React.js and PWA

Full immersion here!

It’s time to say good bye!

When React.js and Progressive Web App technologies are combined, developers can create cross-platform applications with seamless user experiences.

In terms of future trends, PWA development is expected to witness improved browser support, enhanced offline functionality, and increased integration with native platforms.

Security measures will be strengthened, app store acceptance of PWAs will rise, and web standards like web components and HTTP/3 will enable more powerful and efficient PWAs.

By keeping up with these advancements, developers can leverage the full potential of PWAs, delivering modern, engaging, and high-performing web applications to users.

In summary, the combination of React.js and PWAs offers cross-platform compatibility, seamless user experiences, increased performance, and wider reach. Tell us your experience.