Know how to optimize SPA Asset Delivery

Published by

on

In the realm of Single Page Applications (SPAs), the optimization of application performance becomes very significant. This article takes a deep dive into performance enhancement strategies tailored for SPAs, with a specific focus on their implementation within the Angular and React frameworks.

These approaches not only bolster user experience but also tackle issues like prolonged load times and suboptimal resource management.

Whenever the complexity of web applications burgeons, it inevitably leads to the expansion of the application bundle, resulting in extended load times and a diminished user experience.

The adoption of code splitting, lazy loading, and efficient bundling emerges as a compelling solution to combat these challenges, especially within the context of widely-used frameworks like Angular and React

Code Splitting

Code splitting is the process of dividing a codebase into distinct chunks, which are then loaded on demand. This approach ensures that users initially download only the essential code, resulting in faster page loads.

  • Angular
    In Angular, through the Angular Router you can achieve Code Splitting. Routes are associated with components, and when a route is accessed, its corresponding component is loaded. The loadChildren method is key to implementing lazy loading in Angular routes, where modules are loaded only when required.
  • React
    React leverages dynamic import() syntax, a feature of modern JavaScript, for code splitting. With the help of tools like Webpack or Create React App, developers can define split points in the application, allowing React to load each chunk only when it’s needed.

Lazy Loading

Lazy loading defers the loading of non-critical resources at page load time. Instead, these resources are loaded at the moment they are needed.

  • Angular
    Angular’s router supports lazy loading out of the box. By configuring the RouterModule with routes that lazy load modules, Angular can split the application into several bundles and load them on demand.
  • React
    In React, lazy loading can be combined with React’s Suspense component. Suspense allows components to “wait” for something before rendering, making it a perfect fit for lazy loading.

Efficient Bundling

Efficient bundling involves optimizing the package of files sent to the client, since it reduces the file size and minimizes the number of requests needed to load a page.

Examples

Code Splitting and Lazy Loading

React Example

In React, you can use dynamic import() syntax in addition to React’s Suspense and lazy components.

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
        </Switch>
      </Suspense>
    </Router>
  );
}

export default App;

Angular Example

In Angular, you use the Angular Router for lazy loading modules. This is achieved through route configuration.

First, you define a feature module, e.g., AboutModule:

// about.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AboutComponent } from './about.component';
import { RouterModule } from '@angular/router';

@NgModule({
  declarations: [AboutComponent],
  imports: [
    CommonModule,
    RouterModule.forChild([
      { path: '', component: AboutComponent }
    ])
  ]
})
export class AboutModule { }

Next, you configure the main application routes to lazily load this module:

// app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  { path: 'about', loadChildren: () => import('./about/about.module').then(m => m.AboutModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

In this Angular example, the AboutModule is only loaded when the user navigates to the /about route. This improves the initial load time of the application since the code for the About component is not included in the main bundle.

Both of these examples showcase the basic implementation of code splitting and lazy loading in React and Angular. They are foundational for building efficient and performant web applications. For a more detailed implementation, you would typically also handle error states, loading indicators, and possibly preloading strategies.

Conclusion

Implementing code splitting, lazy loading, and efficient bundling is a crucial part of optimizing modern web applications. While the specific implementations in Angular and React differ, the underlying principles remain the same. Adopting these techniques can significantly enhance application performance, ultimately leading to a better user experience.

Further Reading

  1. Angular: Lazy Loading
  2. React: Lazy
  3. React: Suspence
  4. Angular: Ahead-of-time (AOT) compilation
  5. Webpack: Getting Started

Disclaimer: This blog contains the individual opinions and perspectives of Vijay Pandurangan, which are not necessarily indicative of the views of his employer. The author assumes no responsibility for any actions taken or decisions made based on the information presented in this blog. Should any content from this blog be referenced or used in articles, white papers, wikis, blogs, or similar formats, it should be attributed solely to Vijay Pandurangan, independent of his professional affiliations. Please note that the use of his employer’s name in such contexts is not permitted.


Discover more from Vijay Pandurangan

Subscribe now to keep reading and get access to the full archive.

Continue reading