Frontend Development using React.js or Angular

Chapter 13
Performance, Analytics, and Optimization Decisions

Diploma in Full Stack Programming
Frontend Development using React.js or Angular   •   Diploma

Performance, Analytics, and Optimization Decisions

Introduction

A modern React.js or Angular application is successful only when it is both functionally correct and perceptually responsive. Users judge performance through the time required to see useful content, interact with controls, and recover from navigation or network delays. Organisations also judge performance through conversion, retention, accessibility, operational cost, and search visibility. Performance optimization is therefore not a collection of isolated tricks; it is a measurement-led decision process.

This chapter presents a practical framework for measuring Core Web Vitals, bundle size, rendering, network activity, and user behaviour. It then connects those measurements to code splitting, lazy loading, caching, image optimization, memoization, and analytics. The central principle is:

Optimize a measured bottleneck that affects a meaningful user or business outcome, then verify the result with representative evidence.

The examples use concepts common to both React and Angular. React examples use dynamic imports and memoization; Angular examples refer to route-level lazy loading and change detection.

Learning objectives

By the end of this chapter, a learner should be able to:

  1. Explain the principal performance metrics and Core Web Vitals.
  2. Measure bundle, rendering, network, and real-user behaviour using appropriate tools.
  3. Distinguish laboratory testing from field measurement.
  4. Select and justify code splitting, lazy loading, caching, image optimization, and memoization techniques.
  5. Interpret analytics without confusing correlation with causation.
  6. Prioritize optimization work using user impact, technical effort, and risk.
  7. Evaluate performance improvements ethically and communicate them professionally.

1. Performance as an evidence-based discipline

Frontend performance has several dimensions. Loading performance concerns how quickly content appears. Interaction performance concerns whether clicks, typing, and navigation respond promptly. Visual stability concerns whether content unexpectedly moves. Resource efficiency concerns JavaScript, CSS, images, fonts, memory, and network transfer. Business performance concerns outcomes such as checkout completion or task success.

A useful conceptual model is a measurement loop:

  1. Define a user journey and a performance objective.
  2. Measure a baseline under realistic conditions.
  3. Identify the dominant constraint.
  4. Apply the smallest suitable intervention.
  5. Re-measure technically and behaviourally.
  6. Roll out safely and continue monitoring.

Optimization should not mean making every page or component as small as possible. A larger resource that is cached and reused may be preferable to many fragmented requests. Similarly, memoization can reduce computation but increase memory use and code complexity. Decisions require trade-offs.

Important terminology

  • Lab data: Measurements produced in a controlled test environment, such as Lighthouse or WebPageTest.
  • Field data: Measurements collected from real users, devices, browsers, and networks.
  • RUM: Real User Monitoring; collection of performance information from actual sessions.
  • Critical path: Resources and processing required before a user can see or use important content.
  • Long task: A browser main-thread task lasting more than 50 ms, potentially delaying input and rendering.
  • Performance budget: A predefined limit for metrics such as JavaScript transfer size, LCP, or number of requests.
  • Regression: A measurable deterioration after a code or infrastructure change.

2. Core Web Vitals and related metrics

Core Web Vitals are field-oriented indicators of loading, interactivity, and visual stability. The principal metrics are:

MetricWhat it representsCommon “good” target
LCP, Largest Contentful PaintTime until the largest visible content element is rendered≤ 2.5 s
INP, Interaction to Next PaintResponsiveness across user interactions≤ 200 ms
CLS, Cumulative Layout ShiftUnexpected visual movement≤ 0.1

Thresholds are generally evaluated at the 75th percentile of eligible page visits, not by the fastest or average visit. Thresholds and definitions may evolve, so teams should consult current web-platform guidance when establishing a formal standard.

LCP is affected by server response time, resource discovery, download time, and rendering delay. A large hero image, server-rendered heading, or text block may become the LCP element. INP is affected by event-handler work, JavaScript execution, style calculation, layout, and painting. CLS is dimensionless: it reflects impact fraction multiplied by distance fraction for layout-shift events, with browser-defined session-window rules used to accumulate shifts.

The following simplified relationship is useful for diagnosing, not calculating an official LCP value:

LCP ≈ TTFB + resource-discovery delay + resource-download time + render delay

Here, TTFB is time to first byte. The terms are approximate and may overlap; therefore they must not be added mechanically when tasks occur concurrently.

Other valuable metrics include:

  • FCP: First Contentful Paint, the first rendered text, image, or canvas content.
  • TTFB: Time to first byte from the server response.
  • TBT: Total Blocking Time, a lab proxy for main-thread blocking before interaction readiness.
  • FID: First Input Delay, now largely superseded for general responsiveness assessment by INP.
  • Resource timing: DNS, connection, request, response, and transfer timings.
  • Long-task count and duration: Evidence of main-thread contention.

Interpreting percentiles

Suppose 1,000 field visits produce an INP distribution. The 75th percentile is the value at or below which approximately 750 observations fall. It represents a substantial portion of users while avoiding domination by a single extreme outlier. Averages can conceal a poor experience for a minority using slower devices, so percentiles and device/network segmentation are essential.

3. Measuring the application

Laboratory measurement

Browser DevTools Performance and Network panels, Lighthouse, and WebPageTest help reproduce page loads and interactions. A meaningful test records viewport, browser version, CPU throttling, network profile, cache state, geographic location, authentication state, and URL. Compare like with like. A warm-cache test cannot be fairly compared with a cold-cache test.

The Performance panel helps locate long tasks, scripting, style recalculation, layout, paint, and compositing. The Network panel reveals request waterfalls, transfer size, decoded image size, cache status, compression, priority, and blocking relationships. Coverage tools can expose unused JavaScript and CSS, although unused code on one route may be reused on another and should not automatically be removed.

Field measurement

Field data can be collected through browser APIs and a RUM platform. A practical implementation records Web Vitals with a privacy-preserving identifier, route, release version, device category, connection information where available, and timing values. It should avoid collecting page content, keystrokes, or unnecessary personal information.

Field data answers questions lab data cannot: Which users experience slow interactions? Does a change help mobile users? Is performance different by geography, browser, route, or release? However, field data is noisy and may be affected by sampling, consent, ad blockers, and changing user populations.

Measurement discipline

A useful performance report contains:

  • the journey tested;
  • the metric definition and unit;
  • sample size and percentile;
  • cache and network conditions;
  • segmentation by device, browser, geography, and route;
  • release or experiment identifier;
  • confidence or uncertainty information where decisions are consequential.

Do not report “the page is 30% faster” without specifying the metric, population, and comparison. If a metric changes from 4.0 s to 3.0 s, the absolute improvement is 1.0 s and the relative improvement is:

Relative improvement = (4.0 − 3.0) ÷ 4.0 × 100% = 25%

The calculation assumes both values measure the same metric under comparable conditions.

4. Bundle, rendering, and network analysis

Bundle analysis

A production build transforms application modules into browser-delivered assets. Important measures include raw size, compressed transfer size, parsed size, and execution cost. Transfer size depends on compression; parsed and executed size affect CPU and memory. A small compressed bundle can still be expensive to parse and execute.

Bundle analyzers display which packages and modules contribute to each chunk. Common problems include importing an entire utility library for one function, shipping development code, duplicate dependencies, oversized polyfills, and placing infrequently used administration features in the initial bundle.

Tree shaking removes statically unreachable exports, but it is limited by dynamic module patterns and side effects. Package metadata and build configuration must correctly identify side-effectful modules; otherwise removing code can change behaviour.

Rendering and the main thread

The browser generally parses HTML, constructs the DOM and CSSOM, calculates styles and layout, paints pixels, and composites layers. JavaScript competes for main-thread time with these activities. A component that renders thousands of rows, performs expensive filtering, or triggers repeated layout reads and writes may produce long tasks.

In React, unnecessary re-rendering may arise from changing object or function references, state placed too high in the tree, or expensive calculations executed on every render. In Angular, excessive change-detection work, large templates, and impure pipes can cause similar problems. Virtualized lists, pagination, incremental rendering, and server-side filtering can reduce work.

Network analysis

A waterfall should be interpreted as a dependency graph, not merely a list of requests. Critical requests should be discoverable early, appropriately prioritized, compressed, and cacheable. Use modern transport protocols where supported, but do not assume HTTP/2 or HTTP/3 automatically solves oversized resources. A large JavaScript payload still consumes bandwidth and CPU.

Important practices include serving Brotli or gzip where appropriate, using responsive image formats, avoiding render-blocking resources that are not critical, preloading only truly critical resources, and using preconnect selectively for required origins. Excessive third-party scripts can create independent network and privacy risks.

5. Optimization techniques and their trade-offs

Code splitting and lazy loading

Code splitting creates separate chunks that are loaded when needed. Route-level splitting is usually the highest-value starting point because users often visit only part of an application. React can load a component dynamically:

const Reports = React.lazy(() => import('./Reports'));

The component should be rendered within a suitable Suspense boundary. Angular applications commonly use lazy routes, for example with loadChildren or loadComponent, depending on the Angular version and architecture.

Lazy loading reduces initial JavaScript but may introduce a delay at the moment of navigation. Good practice includes meaningful loading states, error recovery, prefetching when user intent is predictable, and avoiding a waterfall in which a lazy component waits for another serial dependency. Split at meaningful user journeys rather than creating many tiny chunks with overhead.

Caching

Caching is a coordination problem among browser cache, CDN, service worker, application data cache, and server. Fingerprinted static assets can usually use a long freshness lifetime because a changed file receives a new URL. HTML commonly needs a shorter lifetime or revalidation so that it discovers current asset names.

A simplified freshness decision is:

Serve from cache if current time − stored time < freshness lifetime

This model assumes a basic freshness policy and ignores revalidation directives, validation headers, cache partitioning, and intermediary behaviour. In production, Cache-Control, ETag, Last-Modified, and deployment strategy must be considered together.

Application-data caching requires correctness rules. A stale-while-revalidate approach can display cached data immediately while requesting a fresh copy, but it must handle mutations, authorization, errors, and invalidation. Never cache private or sensitive responses in a shared cache without an appropriate policy.

Image optimization

Images frequently dominate transfer size and LCP. Select dimensions close to the rendered size, use responsive srcset and sizes, choose AVIF or WebP where compatibility and quality are acceptable, compress without unacceptable visual loss, and reserve layout dimensions using width and height or aspect ratio. Below-the-fold images can use lazy loading; the LCP image generally should not be lazily loaded.

Image optimization has a perceptual constraint: the smallest file is not automatically the best choice. Evaluate sharpness, contrast, text legibility, and accessibility. Provide meaningful alternative text when an image communicates information; use empty alternative text for decorative images.

Memoization

Memoization reuses a previously computed result when inputs are unchanged. In React, memo, useMemo, and useCallback can help when a component or calculation is demonstrably expensive and dependencies are stable. They are not universal speed controls. Comparing dependencies and retaining values also has cost, and unstable object creation can defeat memoization.

In Angular, pure pipes, OnPush change detection, immutable state practices, and careful observable composition can reduce unnecessary work. These techniques require correct change and data-flow assumptions. A memoized result must be invalidated when relevant input changes; stale data is a correctness defect, not a performance success.

Rendering strategies

Client-side rendering can provide rich interactions but may delay useful content on slow devices. Server-side rendering or pre-rendering can improve initial content visibility and search crawling, while hydration introduces its own JavaScript and consistency costs. Streaming and partial hydration are contemporary approaches, but their value depends on application architecture, hosting, and interaction requirements.

6. Analytics and evidence-based prioritization

Analytics should connect technical observations to user journeys. Events might include route view, search submitted, product added, form error, checkout completion, and task abandonment. Each event needs a stable name, documented properties, ownership, retention policy, and validation rules.

A practical event specification records:

FieldExample
Event namecheckout_completed
Required propertiesorder_value, currency, item_count
Contextroute, release, device category
Prohibited datapasswords, full payment data, unnecessary identifiers
Owner and purposeProduct analytics; conversion analysis

Do not infer that a performance change caused a conversion change merely because both moved together. Use controlled experiments when feasible, compare equivalent cohorts, account for seasonality, and examine confidence intervals or uncertainty. Technical and product metrics should be viewed together: a lower LCP with no improvement in task completion may still be valuable, but it changes the next decision.

Privacy is part of engineering quality. Obtain consent where required, minimise data, pseudonymise identifiers, document purposes, honour deletion and opt-out requests, restrict access, and set retention limits. Avoid session recordings that capture sensitive fields. Follow applicable law and organisational policy, including data-protection requirements relevant to the deployment region.

7. A prioritization framework

Teams can rank opportunities using a transparent score rather than personal preference. One simple heuristic is:

Priority score = (User impact × Reach × Evidence strength) ÷ (Effort × Risk)

Each factor may be rated on an agreed ordinal scale, such as 1–5. The score is not a scientific law and has no universal units; it is a communication aid. Definitions must be documented so that scores are comparable within the team. “Evidence strength” should reflect the quality of measurement, not confidence in a favourite solution.

A decision matrix can classify work:

EvidenceImpactRecommended action
StrongHighImplement, measure, and monitor promptly
StrongLowSchedule when opportunity cost is low
WeakHighRun a focused investigation or experiment
WeakLowDefer or avoid speculative complexity

Performance budgets provide an earlier control point. A team may define limits for initial compressed JavaScript, LCP at the 75th percentile, number of long tasks, and CLS. Budgets must be enforced in continuous integration or release monitoring, with documented exceptions for deliberate product changes.

8. Illustrative case study: a slow learning portal

Background

This fictional diploma-level case concerns LearnSpace, a React learning portal. Its home page displays a course catalogue, personalised recommendations, video thumbnails, and analytics scripts. Mobile users report that the page “hangs” after tapping a course.

Problem and baseline

Field monitoring for the mobile segment shows LCP at 4.1 s, INP at 420 ms, and CLS at 0.19 at the 75th percentile. The initial compressed JavaScript is 780 kB. A trace shows a 280 ms long task caused by parsing and executing a charting library and recommendation code. The Network panel shows full-resolution thumbnails, while the DOM contains 1,200 course cards even though only 12 are visible.

Analysis

The evidence indicates multiple bottlenecks: excessive initial JavaScript, expensive rendering, unbounded list work, and image transfer. Analytics also shows that only 8% of home-page users open the recommendations panel. Therefore, loading recommendation code and data eagerly has low reach and poor initial value.

Approach and solution

The team establishes a route-level performance budget and makes the following changes:

  1. The recommendation panel is code-split and loaded on explicit user intent, with a loading and error state.
  2. The course list is paginated and virtualized so that only visible cards are rendered.
  3. Thumbnails use responsive dimensions and modern formats; intrinsic dimensions reserve layout space.
  4. The charting library is imported only on the analytics route.
  5. Stable props and selective React memoization reduce repeated card rendering; profiling verifies that the comparison overhead is worthwhile.
  6. Fingerprinted assets receive long-lived immutable caching, while HTML is revalidated.
  7. RUM records route, release, device category, LCP, INP, CLS, and course-open completion without collecting sensitive content.
  8. A staged rollout compares the new release with the previous release on equivalent mobile cohorts.

Outcome

After rollout, the mobile 75th-percentile LCP is 2.6 s, INP is 190 ms, and CLS is 0.06. Initial compressed JavaScript falls to 410 kB. Course-open completion increases, but the team does not claim that performance alone caused the increase until the cohort analysis is reviewed for other concurrent changes. The recommendation panel’s delayed loading has no material effect on users who never open it and improves the initial journey for most visitors.

Learning points

The case demonstrates that no single optimization solved the problem. Measurement connected a user complaint to bundle execution, rendering volume, and image delivery. The team avoided speculative memoization, separated low-reach features, protected layout stability, and verified technical and behavioural outcomes.

9. Challenges, limitations, and contemporary practice

Performance is difficult because devices, networks, browsers, caches, content, and user behaviour vary. A lab score may improve while real users worsen if the test omits low-end devices. Conversely, a field metric may deteriorate because traffic composition changed rather than because code regressed. Use both forms of evidence.

Optimization can also create accessibility problems. Aggressive animation, delayed content, inaccessible loading states, tiny images, and controls that require excessive JavaScript can harm users. Respect reduced-motion preferences, preserve keyboard access, maintain semantic HTML, and test with assistive technologies.

Third-party services deserve architectural scrutiny. Advertising, chat, maps, A/B testing, and analytics can add requests, CPU work, privacy exposure, and failure modes. Load them only when justified, isolate them where possible, and establish owners and removal criteria.

AI-assisted coding and performance analysis can suggest imports, memoization, or bundle changes, but generated recommendations must be profiled and reviewed. AI may misunderstand data freshness, privacy obligations, framework lifecycle behaviour, or the actual bottleneck. Evidence remains the governing principle.

Best-practice checklist

  • Define performance objectives by journey and user segment.
  • Measure both cold and warm cache behaviour.
  • Use field percentiles, not only averages or a single device.
  • Inspect transfer, parse, execute, and render costs separately.
  • Split routes and rarely used features before applying micro-optimizations.
  • Optimize LCP resources and reserve image layout space.
  • Use caching policies consistent with content sensitivity and deployment.
  • Profile before and after memoization or change-detection adjustments.
  • Connect analytics events to documented product questions.
  • Minimise personal data and respect consent, access, and deletion requirements.
  • Automate budgets and monitor regressions after release.

Chapter Summary

Performance optimization in React and Angular is an evidence-based cycle of measurement, diagnosis, intervention, and verification. Core Web Vitals describe loading, interaction responsiveness, and visual stability, while bundle, trace, network, and RUM data reveal the causes behind user experience. Laboratory tests provide controlled diagnosis; field data reveals actual population outcomes.

High-value interventions commonly include route-level code splitting, intent-aware lazy loading, responsive image delivery, reliable caching, bounded rendering, and carefully justified memoization. Each technique has trade-offs involving latency, memory, complexity, correctness, and maintainability. Analytics should measure meaningful journeys while respecting privacy and should not be interpreted as proof of causation without appropriate comparison. Budgets, percentiles, staged rollout, and continuous monitoring help teams make defensible optimization decisions.

Key Terms

Core Web Vitals: Field-oriented metrics for loading, responsiveness, and visual stability.

LCP: Largest Contentful Paint, indicating when the largest visible content is rendered.

INP: Interaction to Next Paint, measuring responsiveness across interactions.

CLS: Cumulative Layout Shift, measuring unexpected visual movement.

RUM: Real User Monitoring using data from actual sessions.

Lab data: Controlled performance measurements from tools and test environments.

Long task: A main-thread task longer than 50 ms.

Critical path: Work required before important content or interaction is available.

Code splitting: Dividing application code into independently loaded chunks.

Lazy loading: Deferring resource loading until needed or likely to be needed.

Tree shaking: Removing statically unreachable code from a production build.

Memoization: Reusing a computed result when relevant inputs have not changed.

Cache invalidation: Updating or discarding cached data when it is no longer valid.

Performance budget: A predefined acceptable limit for a performance measure.

Waterfall: A timeline showing network request dependencies and durations.

Main thread: The browser thread responsible for scripting and much rendering work.

Percentile: A distribution position below which a specified proportion of observations fall.

Layout shift: An unexpected movement of rendered page content.

Field segmentation: Comparing measurements by groups such as device, route, or geography.

Review Questions

Short Answer Questions

  1. What are the three principal Core Web Vitals, and what user experience does each represent?
  2. Distinguish laboratory data from field data.
  3. Why can a small compressed JavaScript bundle still create performance problems?
  4. State two conditions under which memoization may be inappropriate.
  5. Why should an LCP image generally not be lazily loaded?

Long Answer Questions

  1. Explain how a browser performance trace can distinguish JavaScript, layout, paint, and network bottlenecks.
  2. Discuss route-level code splitting and lazy loading, including their benefits, risks, and implementation considerations in React or Angular.
  3. Explain how caching, cache invalidation, and deployment versioning should work together for static assets and HTML.
  4. Discuss how RUM and analytics can be designed to support performance decisions while protecting user privacy.
  5. Develop a performance-budget strategy for a mobile-first application and explain how regressions should be handled.

Analytical / Application Questions

  1. A page has good LCP but poor INP caused by a 350 ms event handler. Which measurements and interventions would you investigate first, and why?
  2. A team proposes memoizing every React component after a lab score decreases. Critically evaluate this proposal and design a more reliable diagnostic process.
  3. An Angular catalogue loads 2,000 products, although users usually inspect fewer than 20. Propose a measurement-led optimization plan covering rendering, network transfer, images, caching, and analytics.

Multiple Choice Questions with Answers

Question 1

Which Core Web Vital primarily measures unexpected movement of visible page content?

A. LCP

B. INP

C. CLS

D. TTFB

Correct Answer: C. CLS

Question 2

Why are field percentiles generally more useful than a single average for evaluating user performance?

A. They remove the need for any segmentation

B. They show how a substantial portion of real users experience the page

C. They measure only the fastest devices

D. They guarantee causal conclusions

Correct Answer: B. They show how a substantial portion of real users experience the page

Question 3

Which intervention most directly reduces initial JavaScript for a rarely used administration feature?

A. Route-level code splitting

B. Increasing image dimensions

C. Disabling browser caching

D. Rendering more list items

Correct Answer: A. Route-level code splitting

Question 4

A resource changes from 4.0 s to 3.0 s under comparable conditions. What is the relative improvement?

A. 10%

B. 20%

C. 25%

D. 33.3%

Correct Answer: C. 25%

Question 5

Which practice best protects layout stability when loading images?

A. Use lazy loading for every image, including the LCP image

B. Reserve space using intrinsic dimensions or aspect ratio

C. Remove width and height attributes

D. Load images only after all JavaScript executes

Correct Answer: B. Reserve space using intrinsic dimensions or aspect ratio

Question 6

What is a major limitation of laboratory performance testing?

A. It cannot measure any browser timing

B. It always includes every real user network condition

C. It may not represent the diversity of real devices and users

D. It cannot identify long tasks

Correct Answer: C. It may not represent the diversity of real devices and users

Question 7

Which statement about memoization is most accurate?

A. It always improves performance regardless of component size

B. It can help expensive stable computations but adds comparison and memory costs

C. It eliminates the need for profiling

D. It guarantees fresh data after mutations

Correct Answer: B. It can help expensive stable computations but adds comparison and memory costs

Question 8

Which caching approach is generally suitable for fingerprinted static assets?

A. A long freshness lifetime because changed content receives a new URL

B. Never caching them under any circumstances

C. Caching them permanently without versioned URLs

D. Disabling compression to improve invalidation

Correct Answer: A. A long freshness lifetime because changed content receives a new URL

Question 9

What is the main purpose of a RUM system?

A. To compile TypeScript into JavaScript

B. To collect performance information from actual user sessions

C. To replace all accessibility testing

D. To remove unused exports during bundling

Correct Answer: B. To collect performance information from actual user sessions

Question 10

Why should a performance score not be treated as proof that a product change caused higher conversion?

A. Performance metrics cannot be measured in browsers

B. Conversion is unrelated to user behaviour

C. Other changes or population differences may explain the correlation

D. Controlled experiments are never useful

Correct Answer: C. Other changes or population differences may explain the correlation

Frontend Development using React.js or Angular
Chapter 13 of 14