Home Tutorials Training Consulting Books Company Contact us


Get more...

Modern Web Standards Guide. Comprehensive overview of current web technologies including HTML5, CSS3, JavaScript ES6+, HTTP/2, Progressive Web Apps, and essential web APIs. This tutorial provides developers with a solid foundation in modern web standards in approximately 30 minutes of reading.

1. Modern Web Standards Overview

The modern web ecosystem has evolved significantly from static HTML pages to dynamic, interactive applications. Understanding current web standards is crucial for developing robust, accessible, and performant web applications.

1.1. Web Architecture Today

Modern web applications follow a client-server architecture with enhanced capabilities:

  • Web clients (browsers) support advanced JavaScript engines, native APIs, and Progressive Web App features

  • Web servers handle HTTP/2, WebSocket connections, and API endpoints

  • Content Delivery Networks (CDNs) optimize global content delivery

  • Progressive Web Apps blur the line between web and native applications

1.2. Core Web Standards

The web platform is built on several foundational standards:

HTML5

The latest markup language standard providing semantic elements, media support, and form enhancements

CSS3

Advanced styling capabilities including Grid, Flexbox, animations, and responsive design

JavaScript ES6+

Modern JavaScript with modules, async/await, classes, and comprehensive APIs

HTTP/2

Improved protocol with multiplexing, server push, and enhanced performance

Web APIs

Browser-native APIs for device access, storage, and advanced functionality

1.3. Modern Web Development Principles

Contemporary web development follows these key principles:

Performance First

Optimize loading times, runtime performance, and resource usage

Mobile First

Design for mobile devices and progressively enhance for larger screens

Accessibility

Ensure applications are usable by everyone, including users with disabilities

Progressive Enhancement

Build basic functionality first, then add advanced features

Security by Default

Implement HTTPS, Content Security Policy, and secure coding practices

1.4. Browser Capabilities

Modern browsers provide extensive capabilities:

  • JavaScript Engines: V8 (Chrome/Edge), SpiderMonkey (Firefox), JavaScriptCore (Safari)

  • Rendering Engines: Blink (Chrome/Edge), Gecko (Firefox), WebKit (Safari)

  • Developer Tools: Built-in debugging, performance profiling, and testing tools

  • Standards Compliance: Regular updates supporting latest web standards

1.5. Development Ecosystem

The web development ecosystem includes:

  • Build Tools: Webpack, Vite, Parcel for bundling and optimization

  • Frameworks: React, Vue, Angular for application structure

  • Package Managers: npm, yarn for dependency management

  • Testing Tools: Jest, Cypress, Playwright for automated testing

2. HTML5 - Modern Markup Language

HTML5 is the current standard for structuring web content. It provides semantic elements, multimedia support, form enhancements, and APIs for interactive applications.

2.1. Semantic HTML Elements

HTML5 introduces semantic elements that provide meaning to content structure:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Semantic HTML5 Example</title>
</head>
<body>
  <header>
    <h1>My Blog</h1>
    <nav>
      <ul>
        <li><a href="#home">Home</a></li>
        <li><a href="#about">About</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <article>
      <header>
        <h2>Article Title</h2>
        <time datetime="2024-12-28">December 28, 2024</time>
      </header>
      <p>This is the main content of the article...</p>
      <footer>
        <p>Tags: <span>HTML5</span>, <span>Web Development</span></p>
      </footer>
    </article>
    
    <aside>
      <h3>Related Links</h3>
      <ul>
        <li><a href="/related-article">Related Article</a></li>
      </ul>
    </aside>
  </main>

  <footer>
    <p>&copy; 2024 My Blog. All rights reserved.</p>
  </footer>
</body>
</html>

Key semantic elements:

  • <header> - Page or section header

  • <nav> - Navigation links

  • <main> - Primary content area

  • <article> - Independent content pieces

  • <section> - Thematic content groupings

  • <aside> - Sidebar or complementary content

  • <footer> - Page or section footer

2.2. Enhanced Form Elements

HTML5 provides new input types and validation:

<form>
  <fieldset>
    <legend>Contact Information</legend>
    
    <label for="email">Email:</label>
    <input type="email" id="email" required>
    
    <label for="phone">Phone:</label>
    <input type="tel" id="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
    
    <label for="website">Website:</label>
    <input type="url" id="website">
    
    <label for="birthdate">Birth Date:</label>
    <input type="date" id="birthdate">
    
    <label for="age">Age:</label>
    <input type="number" id="age" min="18" max="100">
    
    <label for="volume">Volume:</label>
    <input type="range" id="volume" min="0" max="100" value="50">
    
    <label for="color">Favorite Color:</label>
    <input type="color" id="color">
    
    <button type="submit">Submit</button>
  </fieldset>
</form>

New input types include: email, url, tel, search, date, time, number, range, color

2.3. Native Media Support

HTML5 includes built-in audio and video support:

<!-- Audio Element -->
<audio controls>
  <source src="audio.mp3" type="audio/mpeg">
  <source src="audio.ogg" type="audio/ogg">
  Your browser does not support the audio element.
</audio>

<!-- Video Element -->
<video width="320" height="240" controls poster="thumbnail.jpg">
  <source src="movie.mp4" type="video/mp4">
  <source src="movie.webm" type="video/webm">
  <track kind="subtitles" src="subtitles.vtt" srclang="en" label="English">
  Your browser does not support the video element.
</video>

Benefits: * No plugin dependencies * Programmatic control via JavaScript * Accessibility features built-in * Mobile device optimization

2.4. HTML5 APIs

HTML5 provides JavaScript APIs for enhanced functionality:

Canvas API

2D and 3D graphics rendering

<canvas id="myCanvas" width="200" height="100"></canvas>

<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// Draw a rectangle
ctx.fillStyle = '#FF0000';
ctx.fillRect(10, 10, 50, 50);

// Draw a circle
ctx.beginPath();
ctx.arc(100, 50, 25, 0, 2 * Math.PI);
ctx.fillStyle = '#0000FF';
ctx.fill();
</script>
Web Storage

Client-side data persistence

// Local Storage - persists after browser restart
localStorage.setItem('user', JSON.stringify({name: 'John'}));
const user = JSON.parse(localStorage.getItem('user'));

// Session Storage - cleared when tab closes
sessionStorage.setItem('temp', 'value');
Geolocation

Access user location

navigator.geolocation.getCurrentPosition(
  (position) => {
    console.log('Lat:', position.coords.latitude);
    console.log('Lng:', position.coords.longitude);
  },
  (error) => console.error('Location error:', error)
);

2.5. Accessibility Features

HTML5 improves web accessibility:

ARIA Attributes

Provide additional semantic information

<button aria-label="Close dialog" aria-expanded="false">×</button>
<div role="alert" aria-live="polite">Status message</div>
Semantic Structure

Screen readers understand content hierarchy

Keyboard Navigation

tabindex and focus management

2.6. HTML5 Best Practices

Use Semantic Elements

Choose elements based on meaning, not appearance

Validate Markup

Use W3C validator to ensure standards compliance

Optimize for Performance

Minimize DOM depth and use appropriate elements

Progressive Enhancement

Ensure functionality without JavaScript

Example of well-structured HTML5:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="Complete HTML5 example with modern features">
  <title>Complete HTML5 Example</title>
  <style>
    body {
      font-family: system-ui, -apple-system, sans-serif;
      line-height: 1.6;
      max-width: 1200px;
      margin: 0 auto;
      padding: 1rem;
    }
    header, footer {
      background: #f5f5f5;
      padding: 1rem;
      border-radius: 0.5rem;
    }
    nav ul {
      list-style: none;
      display: flex;
      gap: 1rem;
      padding: 0;
    }
    main {
      display: grid;
      grid-template-columns: 2fr 1fr;
      gap: 2rem;
      margin: 2rem 0;
    }
    @media (max-width: 768px) {
      main {
        grid-template-columns: 1fr;
      }
    }
  </style>
</head>
<body>
  <header>
    <h1>Modern Web Development</h1>
    <nav aria-label="Main navigation">
      <ul>
        <li><a href="#home">Home</a></li>
        <li><a href="#tutorials">Tutorials</a></li>
        <li><a href="#about">About</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <section>
      <article>
        <header>
          <h2>HTML5 Features</h2>
          <time datetime="2024-12-28">Published on December 28, 2024</time>
        </header>
        <p>HTML5 brings semantic meaning to web documents through new elements and APIs.</p>
        
        <details>
          <summary>More information</summary>
          <p>HTML5 includes new form controls, multimedia elements, and JavaScript APIs.</p>
        </details>
      </article>

      <section aria-labelledby="contact-form">
        <h3 id="contact-form">Contact Form</h3>
        <form>
          <label for="name">Name (required):</label>
          <input type="text" id="name" required aria-describedby="name-help">
          <small id="name-help">Please enter your full name</small>

          <label for="email">Email:</label>
          <input type="email" id="email" required>

          <button type="submit">Send Message</button>
        </form>
      </section>
    </section>

    <aside aria-labelledby="sidebar-heading">
      <h3 id="sidebar-heading">Related Topics</h3>
      <ul>
        <li><a href="/css3">CSS3 Guide</a></li>
        <li><a href="/javascript">JavaScript ES6+</a></li>
        <li><a href="/accessibility">Web Accessibility</a></li>
      </ul>
    </aside>
  </main>

  <footer>
    <p>&copy; 2024 Web Standards Tutorial. All rights reserved.</p>
    <p>
      <a href="/privacy">Privacy Policy</a> | 
      <a href="/terms">Terms of Service</a>
    </p>
  </footer>

  <script>
    // Progressive enhancement example
    document.querySelector('form')?.addEventListener('submit', (e) => {
      e.preventDefault();
      alert('Form would be submitted via JavaScript!');
    });
  </script>
</body>
</html>

3. CSS3 - Modern Styling

CSS3 provides powerful styling capabilities including responsive layouts, animations, and advanced selectors. Modern CSS enables developers to create sophisticated designs without relying on external frameworks.

3.1. Modern Layout Systems

CSS3 introduces flexible layout systems that replace older float-based approaches.

CSS Grid

Two-dimensional layout system for complex designs

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  grid-gap: 1rem;
  padding: 1rem;
}

.grid-item {
  background: #f0f0f0;
  padding: 1rem;
  border-radius: 0.5rem;
}

/* Named Grid Lines */
.layout {
  display: grid;
  grid-template-columns: 
    [sidebar-start] 250px 
    [sidebar-end main-start] 1fr 
    [main-end];
  grid-template-rows:
    [header-start] 60px
    [header-end content-start] 1fr
    [content-end footer-start] 40px
    [footer-end];
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: content / main; }
.footer { grid-area: footer; }
Flexbox

One-dimensional layout for component arrangement

.flex-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
}

.flex-item {
  flex: 1 1 200px; /* grow shrink basis */
  min-width: 0; /* Allow items to shrink below content size */
}

/* Navigation Menu */
.nav {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav li {
  flex: 0 0 auto;
}

.nav a {
  display: block;
  padding: 0.5rem 1rem;
  text-decoration: none;
}

/* Card Layout */
.card {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.card-content {
  flex: 1; /* Takes remaining space */
}

.card-actions {
  flex: 0 0 auto; /* Don't grow or shrink */
  margin-top: auto;
}

3.2. Responsive Design

CSS3 media queries enable adaptive designs across devices:

/* Mobile First Approach */
.container {
  width: 100%;
  padding: 0 1rem;
}

/* Tablet styles */
@media (min-width: 768px) {
  .container {
    max-width: 750px;
    margin: 0 auto;
  }
  
  .grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2rem;
  }
}

/* Desktop styles */
@media (min-width: 1024px) {
  .container {
    max-width: 1200px;
  }
  
  .grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Large desktop */
@media (min-width: 1440px) {
  .container {
    max-width: 1400px;
  }
}

/* Dark mode preference */
@media (prefers-color-scheme: dark) {
  body {
    background-color: #1a1a1a;
    color: #ffffff;
  }
}

/* Reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Key responsive design principles:

  • Mobile-first approach: Design for small screens, then enhance

  • Flexible units: Use rem, em, vh, vw instead of fixed pixels

  • Fluid grids: Layouts that adapt to container size

  • Flexible images: max-width: 100% for scalable images

3.3. Animations and Transitions

CSS3 provides native animation capabilities:

Transitions

Smooth property changes

.button {
  background-color: blue;
  transition: background-color 0.3s ease;
}

.button:hover {
  background-color: red;
}
Keyframe Animations

Complex multi-step animations

@keyframes slideIn {
  from {
    transform: translateX(-100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

@keyframes bounce {
  0%, 20%, 50%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-30px);
  }
  60% {
    transform: translateY(-15px);
  }
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

/* Usage */
.slide-in {
  animation: slideIn 0.5s ease-out;
}

.bounce {
  animation: bounce 2s infinite;
}

.pulse {
  animation: pulse 1s ease-in-out infinite alternate;
}

/* Loading spinner */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

3.4. Advanced Selectors

CSS3 introduces powerful selector types:

Attribute Selectors
input[type="email"] { border-color: blue; }
a[href^="https"] { color: green; }
div[class*="card"] { padding: 1rem; }
Pseudo-classes
:nth-child(odd) { background: #f0f0f0; }
:not(.active) { opacity: 0.5; }
:focus-visible { outline: 2px solid blue; }
Pseudo-elements
::before { content: "★"; }
::after { content: ""; display: block; clear: both; }
::first-letter { font-size: 2em; float: left; }

3.5. CSS Custom Properties (Variables)

CSS variables enable maintainable and dynamic styling:

/* Global variables */
:root {
  --primary-color: #3498db;
  --secondary-color: #2c3e50;
  --accent-color: #e74c3c;
  --text-color: #333333;
  --background-color: #ffffff;
  --border-radius: 0.5rem;
  --spacing-unit: 1rem;
  --font-family: system-ui, -apple-system, sans-serif;
}

/* Dark theme */
@media (prefers-color-scheme: dark) {
  :root {
    --text-color: #ffffff;
    --background-color: #1a1a1a;
    --primary-color: #5dade2;
    --secondary-color: #34495e;
  }
}

/* Usage */
.card {
  background-color: var(--background-color);
  color: var(--text-color);
  border-radius: var(--border-radius);
  padding: calc(var(--spacing-unit) * 2);
  font-family: var(--font-family);
}

.button {
  background-color: var(--primary-color);
  color: white;
  border: none;
  border-radius: var(--border-radius);
  padding: var(--spacing-unit);
  font-family: var(--font-family);
}

.button:hover {
  background-color: var(--accent-color);
}

/* Component-specific variables */
.sidebar {
  --sidebar-width: 250px;
  --sidebar-background: var(--secondary-color);
  
  width: var(--sidebar-width);
  background-color: var(--sidebar-background);
}

Benefits: * Reduce code duplication * Enable theming and dark mode * JavaScript can modify values dynamically * Cascade and inheritance support

3.6. Modern CSS Features

Container Queries

Style based on container size, not viewport

.card {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card h2 {
    font-size: 2rem;
  }
}
CSS Cascade Layers

Control specificity and cascade order

@layer base, components, utilities;

@layer base {
  h1 { font-size: 2rem; }
}

@layer components {
  .heading { font-size: 3rem; }
}
Subgrid

Nested grid layouts

.parent {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

.child {
  display: grid;
  grid-template-columns: subgrid;
}

3.7. CSS Best Practices

Organized Architecture

Use methodologies like BEM or utility-first approaches

Performance Optimization
  • Minimize CSS file sizes

  • Avoid complex selectors

  • Use CSS containment for performance

  • Leverage browser caching

Maintainability
  • Use meaningful class names

  • Group related styles

  • Comment complex code

  • Follow consistent formatting

Example of well-structured CSS:

/* Modern CSS Example - Component-based styling */

/* Reset and base styles */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  line-height: 1.5;
  color: #333;
}

/* Layout components */
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 1rem;
}

/* Card component */
.card {
  background: white;
  border-radius: 0.5rem;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

.card__header {
  padding: 1rem;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

.card__title {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
}

.card__content {
  padding: 1rem;
}

.card__actions {
  padding: 0 1rem 1rem;
  display: flex;
  gap: 0.5rem;
}

/* Button component */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 0.25rem;
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: all 0.2s ease;
}

.button--primary {
  background-color: #3b82f6;
  color: white;
}

.button--primary:hover {
  background-color: #2563eb;
}

.button--secondary {
  background-color: #e5e7eb;
  color: #374151;
}

.button--secondary:hover {
  background-color: #d1d5db;
}

/* Utility classes */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

4. JavaScript ES6+ - Modern Web Scripting

JavaScript ES6+ provides modern syntax and powerful features for building interactive web applications. Understanding current JavaScript standards is essential for modern web development.

4.1. Modern JavaScript Syntax

Arrow Functions

Concise function syntax with lexical this binding

// Traditional function
function add(a, b) {
  return a + b;
}

// Arrow function
const add = (a, b) => a + b;

// Arrow function with multiple statements
const processUser = (user) => {
  const processed = { ...user, processed: true };
  return processed;
};
Template Literals

String interpolation and multi-line strings

const name = 'World';
const message = `Hello, ${name}!
This is a multi-line string
with embedded expressions: ${2 + 3}`;
Destructuring

Extract values from arrays and objects

// Object destructuring
const { name, age, email = 'unknown' } = user;

// Array destructuring
const [first, second, ...rest] = numbers;

// Function parameter destructuring
const processUser = ({ name, age }) => {
  console.log(`${name} is ${age} years old`);
};

4.2. ES6 Modules

Modern JavaScript uses modules for code organization:

// math.js
export const PI = 3.14159;
export const add = (a, b) => a + b;
export default function multiply(a, b) {
  return a * b;
}

// app.js
import multiply, { PI, add } from './math.js';
import * as math from './math.js';

console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20

4.3. Asynchronous JavaScript

Promises

Handle asynchronous operations

// Creating a Promise
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data loaded');
    }, 1000);
  });
};

// Using Promises
fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error));
Async/Await

Cleaner asynchronous code

async function loadUserData(userId) {
  try {
    const user = await fetch(`/api/users/${userId}`);
    const userData = await user.json();
    const posts = await fetch(`/api/users/${userId}/posts`);
    const postsData = await posts.json();

    return { user: userData, posts: postsData };
  } catch (error) {
    console.error('Failed to load user data:', error);
    throw error;
  }
}

// Usage
loadUserData(123)
  .then(data => console.log(data))
  .catch(error => console.error(error));

4.4. Classes and Objects

Modern JavaScript provides class-based syntax:

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  // Method
  greet() {
    return `Hello, I'm ${this.name}`;
  }

  // Getter
  get displayName() {
    return this.name.toUpperCase();
  }

  // Setter
  set displayName(value) {
    this.name = value.toLowerCase();
  }

  // Static method
  static fromObject(obj) {
    return new User(obj.name, obj.email);
  }
}

// Inheritance
class AdminUser extends User {
  constructor(name, email, permissions) {
    super(name, email);
    this.permissions = permissions;
  }

  greet() {
    return `${super.greet()} (Admin)`;
  }
}

const user = new User('John', 'john@example.com');
const admin = new AdminUser('Jane', 'jane@example.com', ['read', 'write']);

4.5. Modern Web APIs

Fetch API

Modern HTTP requests

// GET request
const response = await fetch('/api/data');
const data = await response.json();

// POST request
const response = await fetch('/api/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'John', email: 'john@example.com' })
});

// Error handling
if (!response.ok) {
  throw new Error(`HTTP error! status: ${response.status}`);
}
DOM Manipulation

Modern element selection and manipulation

// Element selection
const button = document.querySelector('.submit-button');
const items = document.querySelectorAll('.list-item');

// Event handling
button.addEventListener('click', (event) => {
  event.preventDefault();
  console.log('Button clicked!');
});

// Creating elements
const newElement = document.createElement('div');
newElement.className = 'dynamic-content';
newElement.textContent = 'Dynamic content';
document.body.appendChild(newElement);

// Modern event handling with delegation
document.addEventListener('click', (event) => {
  if (event.target.matches('.dynamic-button')) {
    console.log('Dynamic button clicked!');
  }
});

4.6. Advanced Features

Array Methods

Functional programming with arrays

const numbers = [1, 2, 3, 4, 5];

// Transform data
const doubled = numbers.map(n => n * 2);
const filtered = numbers.filter(n => n > 3);
const sum = numbers.reduce((acc, n) => acc + n, 0);

// Find elements
const found = numbers.find(n => n > 3);
const exists = numbers.some(n => n > 4);
const all = numbers.every(n => n > 0);
Object Methods

Working with objects

const user = { name: 'John', age: 30, city: 'New York' };

// Get keys, values, entries
const keys = Object.keys(user);
const values = Object.values(user);
const entries = Object.entries(user);

// Object composition
const defaults = { theme: 'light', language: 'en' };
const settings = { ...defaults, ...userSettings };

// Object.assign
const merged = Object.assign({}, defaults, userSettings);

4.7. Best Practices

Error Handling

Proper error management

// Custom error classes
class ValidationError extends Error {
  constructor(message, field) {
    super(message);
    this.name = 'ValidationError';
    this.field = field;
  }
}

// Comprehensive error handling
async function processForm(formData) {
  try {
    validateFormData(formData);
    const result = await submitForm(formData);
    return { success: true, data: result };
  } catch (error) {
    if (error instanceof ValidationError) {
      return { success: false, error: error.message, field: error.field };
    }
    console.error('Unexpected error:', error);
    return { success: false, error: 'An unexpected error occurred' };
  }
}
Performance Optimization
// Debouncing
const debounce = (func, delay) => {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(null, args), delay);
  };
};

// Usage
const debouncedSearch = debounce((query) => {
  performSearch(query);
}, 300);

// Throttling
const throttle = (func, limit) => {
  let inThrottle;
  return (...args) => {
    if (!inThrottle) {
      func.apply(null, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
};

5. HTTP/2 and Modern Web Protocols

HTTP/2 represents a major evolution in web communication, providing improved performance and new capabilities. Understanding modern HTTP features is crucial for optimizing web application performance.

5.1. HTTP Protocol Evolution

HTTP/1.1

Traditional protocol with text-based headers and single request per connection

HTTP/2

Binary protocol with multiplexing, server push, and header compression

HTTP/3

Latest standard built on QUIC protocol for improved performance and security

5.2. HTTP/2 Key Features

Multiplexing

Multiple requests over a single connection

Traditional HTTP/1.1 requires multiple connections for parallel requests, causing overhead. HTTP/2 allows unlimited parallel requests over one connection.

// Multiple requests benefit from HTTP/2 multiplexing
const promises = [
  fetch('/api/user'),
  fetch('/api/posts'),
  fetch('/api/comments'),
  fetch('/api/notifications')
];

const results = await Promise.all(promises);
Server Push

Proactive resource delivery

Server can push resources before the client requests them:

# Server configuration example (Nginx)
location / {
  http2_push /css/main.css;
  http2_push /js/app.js;
  http2_push /images/logo.png;
}
Header Compression

HPACK algorithm reduces header overhead

HTTP/2 compresses headers using HPACK, significantly reducing bandwidth usage for requests with similar headers.

5.3. HTTP Methods and Usage

Modern web applications use various HTTP methods for different purposes:

// RESTful API examples
const api = {
  // GET - Retrieve data
  async getUser(id) {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
  },

  // POST - Create new resource
  async createUser(userData) {
    const response = await fetch('/api/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(userData)
    });
    return response.json();
  },

  // PUT - Update entire resource
  async updateUser(id, userData) {
    const response = await fetch(`/api/users/${id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(userData)
    });
    return response.json();
  },

  // PATCH - Partial update
  async updateUserEmail(id, email) {
    const response = await fetch(`/api/users/${id}`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email })
    });
    return response.json();
  },

  // DELETE - Remove resource
  async deleteUser(id) {
    const response = await fetch(`/api/users/${id}`, {
      method: 'DELETE'
    });
    return response.ok;
  }
};

5.4. HTTP Status Codes

Understanding status codes helps with proper error handling:

Success (2xx)
  • 200 OK - Request successful

  • 201 Created - Resource created

  • 204 No Content - Success, no response body

Redirection (3xx)
  • 301 Moved Permanently - Permanent redirect

  • 302 Found - Temporary redirect

  • 304 Not Modified - Cached version is current

Client Error (4xx)
  • 400 Bad Request - Invalid request

  • 401 Unauthorized - Authentication required

  • 403 Forbidden - Access denied

  • 404 Not Found - Resource doesn’t exist

  • 429 Too Many Requests - Rate limiting

Server Error (5xx)
  • 500 Internal Server Error - Server error

  • 502 Bad Gateway - Gateway error

  • 503 Service Unavailable - Service temporarily down

5.5. Important HTTP Headers

Security Headers
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains
Caching Headers
Cache-Control: public, max-age=31536000, immutable
ETag: "abc123"
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
CORS Headers
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

5.6. HTTPS and Security

TLS/SSL

Encryption for secure communication

All modern web applications should use HTTPS:

  • Encrypts data in transit

  • Prevents man-in-the-middle attacks

  • Required for modern web APIs

  • Improves SEO rankings

    Certificate Management

    Free certificates from Let’s Encrypt

    HTTP Strict Transport Security (HSTS)

    Forces HTTPS connections

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

5.7. Performance Optimization

Connection Management
// Connection pooling with fetch
const controller = new AbortController();

// Cancel requests when needed
setTimeout(() => controller.abort(), 5000);

const response = await fetch('/api/data', {
  signal: controller.signal
});
Request Optimization
// Batch multiple operations
const batchRequest = async (operations) => {
  const response = await fetch('/api/batch', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ operations })
  });
  return response.json();
};

// Use with GraphQL or custom batch endpoints
const results = await batchRequest([
  { type: 'getUser', id: 1 },
  { type: 'getPosts', userId: 1 },
  { type: 'getComments', postId: 123 }
]);
Response Compression

Enable gzip/brotli compression on server

# Server configuration enables compression
Content-Encoding: br
Content-Type: application/json
Vary: Accept-Encoding

5.8. Modern HTTP Features

WebSocket Upgrade

Real-time communication

const socket = new WebSocket('wss://example.com/socket');

socket.onopen = () => {
  console.log('Connected to WebSocket');
};

socket.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
};

socket.send(JSON.stringify({ type: 'message', content: 'Hello!' }));
Server-Sent Events

One-way real-time updates

const eventSource = new EventSource('/api/events');

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  updateUI(data);
};

eventSource.addEventListener('user-update', (event) => {
  const userData = JSON.parse(event.data);
  updateUserDisplay(userData);
});

5.9. Best Practices

Error Handling

Comprehensive HTTP error management

async function apiRequest(url, options = {}) {
  try {
    const response = await fetch(url, {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        ...options.headers
      }
    });

    if (!response.ok) {
      const errorData = await response.text();
      throw new Error(`HTTP ${response.status}: ${errorData}`);
    }

    return await response.json();
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Request was cancelled');
    } else if (error.name === 'TypeError') {
      console.error('Network error:', error.message);
    } else {
      console.error('API error:', error.message);
    }
    throw error;
  }
}
Rate Limiting

Implement client-side rate limiting

class RateLimiter {
  constructor(maxRequests, timeWindow) {
    this.maxRequests = maxRequests;
    this.timeWindow = timeWindow;
    this.requests = [];
  }

  async throttle() {
    const now = Date.now();
    this.requests = this.requests.filter(time => now - time < this.timeWindow);

    if (this.requests.length >= this.maxRequests) {
      const oldestRequest = Math.min(...this.requests);
      const waitTime = this.timeWindow - (now - oldestRequest);
      await new Promise(resolve => setTimeout(resolve, waitTime));
    }

    this.requests.push(now);
  }
}

const limiter = new RateLimiter(10, 60000); // 10 requests per minute

async function apiCall(url) {
  await limiter.throttle();
  return fetch(url);
}

6. Modern Web APIs

Modern browsers provide extensive APIs that enable rich, native-like web experiences. These APIs provide access to device capabilities and advanced web functionality.

6.1. Storage APIs

Web Storage

Client-side key-value storage

// Local Storage - persistent across browser sessions
localStorage.setItem('theme', 'dark');
const theme = localStorage.getItem('theme');
localStorage.removeItem('theme');
localStorage.clear();

// Session Storage - cleared when tab closes
sessionStorage.setItem('temp-data', JSON.stringify(data));
const tempData = JSON.parse(sessionStorage.getItem('temp-data'));
IndexedDB

Browser-based NoSQL database

// Open database
const request = indexedDB.open('MyDB', 1);

request.onsuccess = (event) => {
  const db = event.target.result;

  // Create transaction
  const transaction = db.transaction(['users'], 'readwrite');
  const store = transaction.objectStore('users');

  // Add data
  const user = { id: 1, name: 'John', email: 'john@example.com' };
  store.add(user);

  // Get data
  const getRequest = store.get(1);
  getRequest.onsuccess = () => {
    console.log('User:', getRequest.result);
  };
};

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore('users', { keyPath: 'id' });
  store.createIndex('email', 'email', { unique: true });
};

6.2. Geolocation API

Access user’s geographical location:

// Get current position
navigator.geolocation.getCurrentPosition(
  (position) => {
    const { latitude, longitude, accuracy } = position.coords;
    console.log(`Location: ${latitude}, ${longitude}${accuracy}m)`);

    // Use location data
    updateMap(latitude, longitude);
    findNearbyServices(latitude, longitude);
  },
  (error) => {
    switch(error.code) {
      case error.PERMISSION_DENIED:
        console.error('User denied location access');
        break;
      case error.POSITION_UNAVAILABLE:
        console.error('Location information unavailable');
        break;
      case error.TIMEOUT:
        console.error('Location request timed out');
        break;
    }
  },
  {
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 0
  }
);

// Watch position changes
const watchId = navigator.geolocation.watchPosition(
  (position) => {
    updateUserLocation(position.coords);
  },
  (error) => console.error('Location error:', error),
  { enableHighAccuracy: true }
);

// Stop watching
navigator.geolocation.clearWatch(watchId);

6.3. Media APIs

MediaDevices

Access camera and microphone

// Get user media
async function startCamera() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: { width: 1280, height: 720 },
      audio: true
    });

    const video = document.getElementById('video');
    video.srcObject = stream;

    return stream;
  } catch (error) {
    console.error('Error accessing media devices:', error);
  }
}

// Screen capture
async function startScreenShare() {
  try {
    const stream = await navigator.mediaDevices.getDisplayMedia({
      video: true,
      audio: true
    });

    const video = document.getElementById('screen-video');
    video.srcObject = stream;

    return stream;
  } catch (error) {
    console.error('Error accessing display media:', error);
  }
}

// List available devices
async function listDevices() {
  const devices = await navigator.mediaDevices.enumerateDevices();

  devices.forEach((device) => {
    console.log(`${device.kind}: ${device.label} (${device.deviceId})`);
  });
}

6.4. Notifications API

Display system notifications:

// Request permission
async function requestNotificationPermission() {
  const permission = await Notification.requestPermission();

  if (permission === 'granted') {
    console.log('Notifications enabled');
  } else {
    console.log('Notifications denied');
  }

  return permission;
}

// Send notification
function sendNotification(title, options = {}) {
  if (Notification.permission === 'granted') {
    const notification = new Notification(title, {
      body: options.body || 'Default message',
      icon: options.icon || '/icon.png',
      badge: options.badge || '/badge.png',
      tag: options.tag || 'default',
      requireInteraction: options.persistent || false,
      actions: options.actions || []
    });

    notification.onclick = () => {
      window.focus();
      notification.close();
    };

    // Auto-close after 5 seconds
    setTimeout(() => notification.close(), 5000);

    return notification;
  }
}

// Usage
sendNotification('New Message', {
  body: 'You have received a new message',
  icon: '/message-icon.png',
  tag: 'message',
  actions: [
    { action: 'reply', title: 'Reply' },
    { action: 'mark-read', title: 'Mark as Read' }
  ]
});

6.5. Intersection Observer API

Efficiently observe element visibility:

// Lazy loading images
const imageObserver = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        img.classList.remove('lazy');
        imageObserver.unobserve(img);
      }
    });
  },
  {
    threshold: 0.1,
    rootMargin: '50px'
  }
);

// Observe images
document.querySelectorAll('img[data-src]').forEach((img) => {
  imageObserver.observe(img);
});

// Infinite scrolling
const sentinelObserver = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        loadMoreContent();
      }
    });
  },
  { threshold: 1.0 }
);

sentinelObserver.observe(document.querySelector('.loading-sentinel'));

6.6. ResizeObserver API

Monitor element size changes:

const resizeObserver = new ResizeObserver((entries) => {
  entries.forEach((entry) => {
    const { width, height } = entry.contentRect;

    // Responsive behavior based on element size
    if (width < 400) {
      entry.target.classList.add('compact');
    } else {
      entry.target.classList.remove('compact');
    }

    // Update charts or layouts
    if (entry.target.classList.contains('chart')) {
      updateChartSize(entry.target, width, height);
    }
  });
});

// Observe elements
document.querySelectorAll('.responsive-component').forEach((element) => {
  resizeObserver.observe(element);
});

6.7. Web Components APIs

Custom Elements

Define custom HTML elements

class UserCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
  }

  connectedCallback() {
    this.render();
    this.addEventListener('click', this.handleClick);
  }

  disconnectedCallback() {
    this.removeEventListener('click', this.handleClick);
  }

  static get observedAttributes() {
    return ['name', 'email', 'avatar'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (oldValue !== newValue) {
      this.render();
    }
  }

  render() {
    const name = this.getAttribute('name') || 'Unknown';
    const email = this.getAttribute('email') || '';
    const avatar = this.getAttribute('avatar') || '/default-avatar.png';

    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
          border: 1px solid #ccc;
          border-radius: 8px;
          padding: 1rem;
          margin: 0.5rem;
        }

        .avatar {
          width: 50px;
          height: 50px;
          border-radius: 50%;
        }

        .info {
          margin-left: 1rem;
        }

        .container {
          display: flex;
          align-items: center;
        }
      </style>

      <div class="container">
        <img class="avatar" src="${avatar}" alt="${name}">
        <div class="info">
          <h3>${name}</h3>
          <p>${email}</p>
        </div>
      </div>
    `;
  }

  handleClick() {
    this.dispatchEvent(new CustomEvent('user-selected', {
      detail: {
        name: this.getAttribute('name'),
        email: this.getAttribute('email')
      },
      bubbles: true
    }));
  }
}

// Define custom element
customElements.define('user-card', UserCard);

// Usage in HTML
// <user-card name="John Doe" email="john@example.com" avatar="/john.jpg"></user-card>

6.8. Web Workers API

Run JavaScript in background threads:

// main.js
const worker = new Worker('/js/worker.js');

// Send data to worker
worker.postMessage({
  command: 'process',
  data: largeDataArray
});

// Receive results from worker
worker.onmessage = (event) => {
  const { command, result } = event.data;

  if (command === 'progress') {
    updateProgressBar(result.percentage);
  } else if (command === 'complete') {
    displayResults(result.data);
    worker.terminate(); // Clean up
  }
};

worker.onerror = (error) => {
  console.error('Worker error:', error);
};

// worker.js
self.onmessage = (event) => {
  const { command, data } = event.data;

  if (command === 'process') {
    const total = data.length;
    const results = [];

    for (let i = 0; i < total; i++) {
      // Intensive computation
      const processed = processItem(data[i]);
      results.push(processed);

      // Report progress every 100 items
      if (i % 100 === 0) {
        self.postMessage({
          command: 'progress',
          result: { percentage: (i / total) * 100 }
        });
      }
    }

    // Send final results
    self.postMessage({
      command: 'complete',
      result: { data: results }
    });
  }
};

function processItem(item) {
  // Simulate heavy computation
  let result = item;
  for (let i = 0; i < 1000000; i++) {
    result = Math.sin(result);
  }
  return result;
}

6.9. Service Worker API

Enable offline functionality and background processing:

// Register service worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then((registration) => {
      console.log('SW registered:', registration);
    })
    .catch((error) => {
      console.error('SW registration failed:', error);
    });
}

// sw.js (Service Worker)
const CACHE_NAME = 'my-app-v1';
const urlsToCache = [
  '/',
  '/css/main.css',
  '/js/app.js',
  '/images/logo.png'
];

// Install event - cache resources
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => cache.addAll(urlsToCache))
  );
});

// Fetch event - serve from cache
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then((response) => {
        // Return cached version or fetch from network
        return response || fetch(event.request);
      })
  );
});

// Background sync
self.addEventListener('sync', (event) => {
  if (event.tag === 'background-sync') {
    event.waitUntil(syncData());
  }
});

// Push notifications
self.addEventListener('push', (event) => {
  const options = {
    body: event.data.text(),
    icon: '/icon.png',
    badge: '/badge.png'
  };

  event.waitUntil(
    self.registration.showNotification('Push Notification', options)
  );
});

7. Progressive Web Apps (PWAs)

Progressive Web Apps combine the best features of web and native applications. PWAs provide app-like experiences with offline functionality, push notifications, and installability.

7.1. PWA Characteristics

Progressive

Works for every user, regardless of browser choice

Responsive

Fits any form factor: desktop, mobile, tablet

Connectivity Independent

Enhanced with service workers to work offline

App-like

Feels like an app with app-style interactions and navigation

Secure

Served via HTTPS to prevent tampering

Discoverable

Identifiable as "applications" via W3C manifests

Re-engageable

Push notifications keep users engaged

Installable

Can be installed on device home screen

Linkable

Easily shared via URL without complex installation

7.2. Web App Manifest

The manifest provides metadata about your web application:

{
  "name": "My Progressive Web App",
  "short_name": "MyPWA",
  "description": "A sample progressive web application",
  "start_url": "/",
  "display": "standalone",
  "orientation": "portrait-primary",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "scope": "/",
  "lang": "en-US",
  "dir": "ltr",
  "icons": [
    {
      "src": "/icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ],
  "shortcuts": [
    {
      "name": "New Message",
      "short_name": "New",
      "description": "Create a new message",
      "url": "/compose",
      "icons": [
        {
          "src": "/icons/compose.png",
          "sizes": "96x96"
        }
      ]
    }
  ],
  "categories": ["productivity", "communication"],
  "screenshots": [
    {
      "src": "/screenshots/desktop.png",
      "sizes": "1280x720",
      "type": "image/png",
      "form_factor": "wide"
    },
    {
      "src": "/screenshots/mobile.png",
      "sizes": "375x667",
      "type": "image/png",
      "form_factor": "narrow"
    }
  ]
}

Link the manifest in your HTML:

<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#000000">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="MyPWA">

7.3. Service Worker Implementation

Service workers enable offline functionality and background processing:

// Register service worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then((registration) => {
        console.log('SW registered: ', registration);

        // Check for updates
        registration.addEventListener('updatefound', () => {
          const newWorker = registration.installing;
          newWorker.addEventListener('statechange', () => {
            if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
              // New version available
              showUpdateNotification();
            }
          });
        });
      })
      .catch((registrationError) => {
        console.log('SW registration failed: ', registrationError);
      });
  });
}

// Show update notification
function showUpdateNotification() {
  const notification = document.createElement('div');
  notification.innerHTML = `
    <div class="update-notification">
      <p>A new version is available!</p>
      <button onclick="updateApp()">Update</button>
      <button onclick="dismissUpdate()">Later</button>
    </div>
  `;
  document.body.appendChild(notification);
}

function updateApp() {
  navigator.serviceWorker.getRegistration().then((registration) => {
    if (registration.waiting) {
      registration.waiting.postMessage({ type: 'SKIP_WAITING' });
    }
  });
  location.reload();
}

Advanced Service Worker:

// sw.js
const CACHE_NAME = 'pwa-cache-v1';
const RUNTIME_CACHE = 'runtime-cache';

// Resources to cache immediately
const PRECACHE_URLS = [
  '/',
  '/css/main.css',
  '/js/app.js',
  '/offline.html',
  '/icons/icon-192x192.png'
];

// Install event
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => cache.addAll(PRECACHE_URLS))
      .then(() => self.skipWaiting())
  );
});

// Activate event
self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames
          .filter((cacheName) => cacheName !== CACHE_NAME && cacheName !== RUNTIME_CACHE)
          .map((cacheName) => caches.delete(cacheName))
      );
    }).then(() => self.clients.claim())
  );
});

// Fetch event with caching strategies
self.addEventListener('fetch', (event) => {
  const { request } = event;
  const url = new URL(request.url);

  // Handle API requests
  if (url.pathname.startsWith('/api/')) {
    event.respondWith(networkFirst(request));
    return;
  }

  // Handle static assets
  if (request.destination === 'image' || request.destination === 'script' || request.destination === 'style') {
    event.respondWith(cacheFirst(request));
    return;
  }

  // Handle pages
  event.respondWith(staleWhileRevalidate(request));
});

// Caching strategies
async function networkFirst(request) {
  try {
    const response = await fetch(request);
    const cache = await caches.open(RUNTIME_CACHE);
    cache.put(request, response.clone());
    return response;
  } catch (error) {
    const cachedResponse = await caches.match(request);
    return cachedResponse || new Response('Offline', { status: 503 });
  }
}

async function cacheFirst(request) {
  const cachedResponse = await caches.match(request);
  if (cachedResponse) {
    return cachedResponse;
  }

  try {
    const response = await fetch(request);
    const cache = await caches.open(RUNTIME_CACHE);
    cache.put(request, response.clone());
    return response;
  } catch (error) {
    return new Response('Not found', { status: 404 });
  }
}

async function staleWhileRevalidate(request) {
  const cache = await caches.open(RUNTIME_CACHE);
  const cachedResponse = await cache.match(request);

  const networkRequest = fetch(request).then((response) => {
    cache.put(request, response.clone());
    return response;
  }).catch(() => {
    // Return offline page for navigation requests
    if (request.mode === 'navigate') {
      return cache.match('/offline.html');
    }
    throw error;
  });

  return cachedResponse || networkRequest;
}

// Background sync
self.addEventListener('sync', (event) => {
  if (event.tag === 'sync-data') {
    event.waitUntil(syncOfflineData());
  }
});

async function syncOfflineData() {
  // Sync data that was stored while offline
  const offlineActions = await getOfflineActions();

  for (const action of offlineActions) {
    try {
      await fetch('/api/sync', {
        method: 'POST',
        body: JSON.stringify(action),
        headers: { 'Content-Type': 'application/json' }
      });
      await removeOfflineAction(action.id);
    } catch (error) {
      console.error('Sync failed for action:', action.id);
    }
  }
}

7.4. App Installation

Handle PWA installation prompts:

let deferredPrompt;
const installButton = document.getElementById('install-button');

// Listen for beforeinstallprompt event
window.addEventListener('beforeinstallprompt', (event) => {
  // Prevent Chrome 67 and earlier from automatically showing the prompt
  event.preventDefault();

  // Store the event so it can be triggered later
  deferredPrompt = event;

  // Show install button
  installButton.style.display = 'block';

  installButton.addEventListener('click', () => {
    // Show the prompt
    deferredPrompt.prompt();

    // Wait for the user to respond to the prompt
    deferredPrompt.userChoice.then((choiceResult) => {
      if (choiceResult.outcome === 'accepted') {
        console.log('User accepted the A2HS prompt');
        trackEvent('pwa_install', 'accepted');
      } else {
        console.log('User dismissed the A2HS prompt');
        trackEvent('pwa_install', 'dismissed');
      }
      deferredPrompt = null;
      installButton.style.display = 'none';
    });
  });
});

// Listen for app installed event
window.addEventListener('appinstalled', (event) => {
  console.log('PWA was installed');
  trackEvent('pwa_install', 'completed');

  // Hide install button
  installButton.style.display = 'none';

  // Show welcome message
  showWelcomeMessage();
});

// Check if app is running in standalone mode
function isStandalone() {
  return window.matchMedia('(display-mode: standalone)').matches ||
         window.navigator.standalone === true;
}

if (isStandalone()) {
  // App is running in standalone mode
  document.body.classList.add('standalone');
}

7.5. Push Notifications

Implement push notifications for user engagement:

// Request notification permission
async function requestNotificationPermission() {
  if (!('Notification' in window)) {
    console.warn('Notifications not supported');
    return false;
  }

  if (Notification.permission === 'granted') {
    return true;
  }

  if (Notification.permission === 'denied') {
    console.warn('Notifications denied by user');
    return false;
  }

  const permission = await Notification.requestPermission();
  return permission === 'granted';
}

// Subscribe to push notifications
async function subscribeToPushNotifications() {
  const hasPermission = await requestNotificationPermission();
  if (!hasPermission) return;

  const registration = await navigator.serviceWorker.ready;

  try {
    const subscription = await registration.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
    });

    // Send subscription to server
    await fetch('/api/subscribe', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(subscription)
    });

    console.log('Push subscription successful');
  } catch (error) {
    console.error('Push subscription failed:', error);
  }
}

// Handle push events in service worker
self.addEventListener('push', (event) => {
  const data = event.data ? event.data.json() : {};

  const options = {
    body: data.body || 'New notification',
    icon: '/icons/icon-192x192.png',
    badge: '/icons/badge-72x72.png',
    data: data.data || {},
    actions: [
      {
        action: 'view',
        title: 'View',
        icon: '/icons/view.png'
      },
      {
        action: 'dismiss',
        title: 'Dismiss',
        icon: '/icons/dismiss.png'
      }
    ],
    requireInteraction: true,
    tag: data.tag || 'default'
  };

  event.waitUntil(
    self.registration.showNotification(data.title || 'Notification', options)
  );
});

// Handle notification clicks
self.addEventListener('notificationclick', (event) => {
  event.notification.close();

  const action = event.action;
  const data = event.notification.data;

  event.waitUntil(
    clients.openWindow(data.url || '/')
  );
});

7.6. PWA Best Practices

Performance
  • Implement efficient caching strategies

  • Optimize critical rendering path

  • Use resource prioritization

  • Minimize main thread work

User Experience
  • Provide meaningful offline experiences

  • Show connection status indicators

  • Handle failed requests gracefully

  • Implement smooth animations and transitions

Security
  • Serve over HTTPS

  • Validate all inputs

  • Implement Content Security Policy

  • Regular security audits

Testing
  • Test offline functionality

  • Validate on multiple devices

  • Use Lighthouse PWA audit

  • Monitor Core Web Vitals

Example PWA architecture:

class PWAApp {
  constructor() {
    this.isOnline = navigator.onLine;
    this.offlineQueue = [];

    this.init();
  }

  async init() {
    // Register service worker
    await this.registerServiceWorker();

    // Setup offline handling
    this.setupOfflineHandling();

    // Setup push notifications
    await this.setupPushNotifications();

    // Setup installation prompt
    this.setupInstallPrompt();
  }

  async registerServiceWorker() {
    if ('serviceWorker' in navigator) {
      const registration = await navigator.serviceWorker.register('/sw.js');
      console.log('Service Worker registered:', registration);
    }
  }

  setupOfflineHandling() {
    window.addEventListener('online', () => {
      this.isOnline = true;
      this.processOfflineQueue();
      this.showConnectionStatus('online');
    });

    window.addEventListener('offline', () => {
      this.isOnline = false;
      this.showConnectionStatus('offline');
    });
  }

  async processOfflineQueue() {
    while (this.offlineQueue.length > 0) {
      const request = this.offlineQueue.shift();
      try {
        await this.sendRequest(request);
      } catch (error) {
        console.error('Failed to process offline request:', error);
        this.offlineQueue.unshift(request);
        break;
      }
    }
  }

  showConnectionStatus(status) {
    const banner = document.createElement('div');
    banner.className = `connection-banner ${status}`;
    banner.textContent = status === 'online' ?
      'Connection restored' : 'You are offline';

    document.body.appendChild(banner);

    setTimeout(() => banner.remove(), 3000);
  }
}

// Initialize PWA
const app = new PWAApp();

8. Web Accessibility (a11y)

Web accessibility ensures that websites and applications are usable by everyone, including people with disabilities. Implementing accessibility features improves user experience for all users and is often required by law.

8.1. WCAG Principles

The Web Content Accessibility Guidelines (WCAG) are built on four principles:

Perceivable

Information must be presentable in ways users can perceive

Operable

User interface components must be operable

Understandable

Information and UI operation must be understandable

Robust

Content must be robust enough for various assistive technologies

8.2. Semantic HTML for Accessibility

Use proper HTML elements to convey meaning:

<!-- Good: Semantic button -->
<button type="button" onclick="toggleMenu()">Menu</button>

<!-- Avoid: Div styled as button -->
<div class="button" onclick="toggleMenu()">Menu</div>

<!-- Good: Proper heading hierarchy -->
<h1>Main Title</h1>
  <h2>Section Title</h2>
    <h3>Subsection Title</h3>

<!-- Good: Semantic form elements -->
<form>
  <fieldset>
    <legend>Personal Information</legend>

    <label for="name">Full Name (required)</label>
    <input type="text" id="name" required aria-describedby="name-help">
    <small id="name-help">Enter your first and last name</small>

    <label for="email">Email</label>
    <input type="email" id="email" aria-describedby="email-error">
    <div id="email-error" aria-live="polite"></div>
  </fieldset>
</form>

<!-- Good: Navigation structure -->
<nav aria-label="Main navigation">
  <ul>
    <li><a href="/" aria-current="page">Home</a></li>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

8.3. ARIA (Accessible Rich Internet Applications)

ARIA provides semantic information for complex interactive elements:

ARIA Roles

Define what an element is or does

<div role="button" tabindex="0">Custom Button</div>
<div role="alert">Error message</div>
<div role="dialog" aria-labelledby="dialog-title" aria-modal="true">
  <h2 id="dialog-title">Confirmation</h2>
  <p>Are you sure you want to delete this item?</p>
  <button>Yes</button>
  <button>No</button>
</div>

<ul role="tablist">
  <li role="tab" aria-selected="true" aria-controls="panel1">Tab 1</li>
  <li role="tab" aria-selected="false" aria-controls="panel2">Tab 2</li>
</ul>
<div id="panel1" role="tabpanel">Content 1</div>
<div id="panel2" role="tabpanel" hidden>Content 2</div>
ARIA Properties

Describe element properties

<!-- Labels -->
<button aria-label="Close dialog">×</button>
<input type="password" aria-labelledby="pwd-label" aria-describedby="pwd-help">
<label id="pwd-label">Password</label>
<div id="pwd-help">Must be at least 8 characters</div>

<!-- States -->
<button aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu" hidden>...</ul>

<input type="checkbox" aria-checked="mixed"> <!-- Indeterminate -->
<button aria-pressed="true">Toggle Button</button>

<!-- Relationships -->
<h2 id="settings-title">Settings</h2>
<div role="region" aria-labelledby="settings-title">
  <!-- Settings content -->
</div>
ARIA Live Regions

Announce dynamic content changes

<!-- Polite announcements -->
<div aria-live="polite" id="status"></div>

<!-- Assertive announcements (interrupts) -->
<div aria-live="assertive" id="errors"></div>

<!-- Atomic updates -->
<div aria-live="polite" aria-atomic="true" id="timer">
  Time remaining: 5:00
</div>

<script>
// Update live regions
function showStatus(message) {
  document.getElementById('status').textContent = message;
}

function showError(message) {
  document.getElementById('errors').textContent = message;
}

// Usage
showStatus('Data saved successfully');
showError('Please correct the highlighted errors');
</script>

8.4. Keyboard Navigation

Ensure all functionality is accessible via keyboard:

<!-- Focus management -->
<div class="modal" role="dialog" aria-labelledby="modal-title">
  <h2 id="modal-title" tabindex="-1">Modal Title</h2>
  <button class="close" aria-label="Close modal">×</button>
  <!-- Modal content -->
  <button class="confirm">Confirm</button>
</div>

<script>
class Modal {
  constructor(element) {
    this.element = element;
    this.focusableElements = this.element.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    this.firstFocusable = this.focusableElements[0];
    this.lastFocusable = this.focusableElements[this.focusableElements.length - 1];
  }

  open() {
    // Store previous focus
    this.previousFocus = document.activeElement;

    this.element.style.display = 'block';

    // Focus title
    this.element.querySelector('#modal-title').focus();

    // Trap focus within modal
    this.element.addEventListener('keydown', this.trapFocus.bind(this));
    document.addEventListener('keydown', this.handleEscape.bind(this));
  }

  close() {
    this.element.style.display = 'none';

    // Restore previous focus
    if (this.previousFocus) {
      this.previousFocus.focus();
    }

    // Remove event listeners
    this.element.removeEventListener('keydown', this.trapFocus);
    document.removeEventListener('keydown', this.handleEscape);
  }

  trapFocus(event) {
    if (event.key === 'Tab') {
      if (event.shiftKey) {
        // Shift + Tab
        if (document.activeElement === this.firstFocusable) {
          event.preventDefault();
          this.lastFocusable.focus();
        }
      } else {
        // Tab
        if (document.activeElement === this.lastFocusable) {
          event.preventDefault();
          this.firstFocusable.focus();
        }
      }
    }
  }

  handleEscape(event) {
    if (event.key === 'Escape') {
      this.close();
    }
  }
}

// Custom dropdown with keyboard support
class AccessibleDropdown {
  constructor(element) {
    this.element = element;
    this.button = element.querySelector('[role="button"]');
    this.menu = element.querySelector('[role="menu"]');
    this.items = element.querySelectorAll('[role="menuitem"]');
    this.currentIndex = -1;

    this.setupEventListeners();
  }

  setupEventListeners() {
    this.button.addEventListener('click', () => this.toggle());
    this.button.addEventListener('keydown', (e) => this.handleButtonKeydown(e));

    this.items.forEach((item, index) => {
      item.addEventListener('click', () => this.selectItem(index));
      item.addEventListener('keydown', (e) => this.handleItemKeydown(e, index));
    });
  }

  handleButtonKeydown(event) {
    switch (event.key) {
      case 'ArrowDown':
      case 'ArrowUp':
      case 'Enter':
      case ' ':
        event.preventDefault();
        this.open();
        this.focusItem(0);
        break;
    }
  }

  handleItemKeydown(event, index) {
    switch (event.key) {
      case 'ArrowDown':
        event.preventDefault();
        this.focusItem(index + 1);
        break;
      case 'ArrowUp':
        event.preventDefault();
        this.focusItem(index - 1);
        break;
      case 'Home':
        event.preventDefault();
        this.focusItem(0);
        break;
      case 'End':
        event.preventDefault();
        this.focusItem(this.items.length - 1);
        break;
      case 'Enter':
      case ' ':
        event.preventDefault();
        this.selectItem(index);
        break;
      case 'Escape':
        event.preventDefault();
        this.close();
        this.button.focus();
        break;
    }
  }
}
</script>

8.5. Color and Contrast

Ensure sufficient color contrast and don’t rely solely on color:

/* Good contrast ratios */
.text-normal {
  color: #333333; /* 12.63:1 ratio on white */
  background-color: #ffffff;
}

.text-large {
  color: #666666; /* 5.74:1 ratio - acceptable for large text */
  background-color: #ffffff;
  font-size: 18px;
  font-weight: bold;
}

/* Error states - don't rely only on color */
.error {
  color: #d32f2f;
  border: 2px solid #d32f2f;
}

.error::before {
  content: "⚠ ";
  font-weight: bold;
}

/* Focus indicators */
.focusable:focus {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

/* High contrast mode support */
@media (prefers-contrast: high) {
  .card {
    border: 2px solid;
  }
}

/* Respect user's motion preferences */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Color blind friendly palette */
:root {
  --accessible-blue: #005fcc;
  --accessible-orange: #ff6f00;
  --accessible-green: #00c853;
  --accessible-red: #d32f2f;
}

8.6. Images and Media

Provide alternative text and captions:

<!-- Informative images -->
<img src="chart.png" alt="Sales increased 25% from 2023 to 2024">

<!-- Decorative images -->
<img src="decoration.png" alt="" role="presentation">

<!-- Complex images -->
<img src="complex-chart.png" alt="Quarterly sales data" aria-describedby="chart-description">
<div id="chart-description">
  <p>The chart shows quarterly sales for 2024:</p>
  <ul>
    <li>Q1: $100,000</li>
    <li>Q2: $150,000</li>
    <li>Q3: $125,000</li>
    <li>Q4: $175,000</li>
  </ul>
</div>

<!-- Videos with captions -->
<video controls>
  <source src="video.mp4" type="video/mp4">
  <track kind="subtitles" src="subtitles-en.vtt" srclang="en" label="English">
  <track kind="captions" src="captions-en.vtt" srclang="en" label="English Captions">
  <p>Your browser doesn't support HTML5 video.
     <a href="video.mp4">Download the video</a>.</p>
</video>

<!-- Audio with transcripts -->
<audio controls>
  <source src="podcast.mp3" type="audio/mpeg">
  <p>Your browser doesn't support HTML5 audio.</p>
</audio>
<details>
  <summary>Transcript</summary>
  <p>Full transcript of the audio content...</p>
</details>

8.7. Accessible Forms

Create forms that work well with assistive technologies:

<form novalidate aria-labelledby="form-title">
  <h2 id="form-title">Contact Form</h2>

  <fieldset>
    <legend>Personal Information</legend>

    <div class="form-group">
      <label for="firstName">First Name *</label>
      <input
        type="text"
        id="firstName"
        name="firstName"
        required
        aria-invalid="false"
        aria-describedby="firstName-error"
      >
      <div id="firstName-error" class="error-message" aria-live="polite"></div>
    </div>

    <div class="form-group">
      <label for="email">Email Address *</label>
      <input
        type="email"
        id="email"
        name="email"
        required
        autocomplete="email"
        aria-describedby="email-help email-error"
      >
      <div id="email-help" class="help-text">We'll never share your email</div>
      <div id="email-error" class="error-message" aria-live="polite"></div>
    </div>

    <fieldset>
      <legend>Preferred Contact Method</legend>
      <div class="radio-group">
        <input type="radio" id="contact-email" name="contactMethod" value="email">
        <label for="contact-email">Email</label>
      </div>
      <div class="radio-group">
        <input type="radio" id="contact-phone" name="contactMethod" value="phone">
        <label for="contact-phone">Phone</label>
      </div>
    </fieldset>

    <div class="form-group">
      <label for="message">Message *</label>
      <textarea
        id="message"
        name="message"
        required
        maxlength="500"
        aria-describedby="message-count message-error"
      ></textarea>
      <div id="message-count" aria-live="polite">0/500 characters</div>
      <div id="message-error" class="error-message" aria-live="polite"></div>
    </div>
  </fieldset>

  <div class="form-actions">
    <button type="submit">Send Message</button>
    <button type="reset">Clear Form</button>
  </div>

  <div id="form-status" aria-live="polite" aria-atomic="true"></div>
</form>

<script>
// Accessible form validation
class AccessibleForm {
  constructor(form) {
    this.form = form;
    this.setupValidation();
  }

  setupValidation() {
    this.form.addEventListener('submit', (e) => this.handleSubmit(e));

    // Real-time validation for better UX
    this.form.querySelectorAll('input, textarea').forEach(field => {
      field.addEventListener('blur', () => this.validateField(field));
      field.addEventListener('input', () => this.clearError(field));
    });
  }

  validateField(field) {
    const isValid = field.checkValidity();
    const errorElement = document.getElementById(`${field.id}-error`);

    field.setAttribute('aria-invalid', !isValid);

    if (!isValid) {
      const errorMessage = this.getErrorMessage(field);
      errorElement.textContent = errorMessage;
    } else {
      errorElement.textContent = '';
    }
  }

  getErrorMessage(field) {
    if (field.validity.valueMissing) {
      return `${this.getFieldName(field)} is required.`;
    }
    if (field.validity.typeMismatch) {
      return `Please enter a valid ${field.type}.`;
    }
    if (field.validity.tooLong) {
      return `${this.getFieldName(field)} is too long.`;
    }
    return 'Please correct this field.';
  }

  getFieldName(field) {
    const label = this.form.querySelector(`label[for="${field.id}"]`);
    return label ? label.textContent.replace(' *', '') : field.name;
  }
}

// Character counter
function updateCharacterCount(textarea) {
  const counter = document.getElementById(`${textarea.id}-count`);
  const current = textarea.value.length;
  const max = textarea.maxLength;

  counter.textContent = `${current}/${max} characters`;

  if (current > max * 0.9) {
    counter.classList.add('warning');
  } else {
    counter.classList.remove('warning');
  }
}
</script>

8.8. Accessibility Testing

Automated Testing

Use tools like axe-core for automated testing

// Install: npm install @axe-core/react
import { axe, toHaveNoViolations } from 'jest-axe';

expect.extend(toHaveNoViolations);

test('should not have accessibility violations', async () => {
  const { container } = render(<MyComponent />);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

// Manual testing with axe in browser
if (process.env.NODE_ENV === 'development') {
  import('@axe-core/react').then(axe => {
    axe.default(React, ReactDOM, 1000);
  });
}
Manual Testing Checklist
  • Navigate entire site using only keyboard

  • Test with screen reader (NVDA, JAWS, VoiceOver)

  • Verify color contrast meets WCAG standards

  • Test with 200% zoom

  • Verify all images have appropriate alt text

  • Check form labels and error messages

  • Test focus indicators are visible

  • Verify heading hierarchy is logical

8.9. Accessibility Resources

Guidelines and Standards
  • WCAG 2.1 AA compliance

  • Section 508 (US government)

  • EN 301 549 (European standard)

  • ADA compliance

Testing Tools
  • axe DevTools browser extension

  • WAVE Web Accessibility Evaluator

  • Lighthouse accessibility audit

  • Color contrast analyzers

  • Screen readers (NVDA, JAWS, VoiceOver, Talkback)

9. Web Performance Optimization

Web performance directly impacts user experience, conversion rates, and search engine rankings. Modern web applications must be optimized for speed across all devices and network conditions.

9.1. Core Web Vitals

Google’s Core Web Vitals measure user experience quality:

Largest Contentful Paint (LCP)

Loading performance - should occur within 2.5 seconds

First Input Delay (FID)

Interactivity - should be less than 100 milliseconds

Cumulative Layout Shift (CLS)

Visual stability - should be less than 0.1

First Contentful Paint (FCP)

Time when first content appears - should be under 1.8 seconds

Time to Interactive (TTI)

When page becomes fully interactive

9.2. Loading Optimization

Resource Prioritization

Load critical resources first

<!DOCTYPE html>
<html>
<head>
  <!-- Critical CSS inline -->
  <style>
    /* Above-the-fold styles */
    body { font-family: system-ui; margin: 0; }
    .header { background: #333; color: white; padding: 1rem; }
  </style>

  <!-- Preload critical resources -->
  <link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
  <link rel="preload" href="/css/critical.css" as="style">
  <link rel="preload" href="/js/main.js" as="script">

  <!-- DNS prefetch for external resources -->
  <link rel="dns-prefetch" href="//fonts.googleapis.com">
  <link rel="dns-prefetch" href="//api.example.com">

  <!-- Preconnect to critical origins -->
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

  <!-- Load non-critical CSS asynchronously -->
  <link rel="preload" href="/css/non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/css/non-critical.css"></noscript>
</head>
<body>
  <!-- Critical above-the-fold content -->
  <header class="header">
    <h1>My Website</h1>
  </header>

  <!-- Lazy load non-critical images -->
  <img src="placeholder.jpg" data-src="hero-image.jpg" class="lazy" alt="Hero image">

  <!-- Load JavaScript at the end -->
  <script src="/js/main.js" defer></script>
</body>
</html>
Code Splitting

Split code into smaller chunks

// Dynamic imports for code splitting
const loadFeature = async () => {
  const { AdvancedFeature } = await import('./advanced-feature.js');
  return new AdvancedFeature();
};

// Route-based code splitting
const router = {
  async loadRoute(routeName) {
    switch (routeName) {
      case 'home':
        const { HomePage } = await import('./pages/home.js');
        return new HomePage();
      case 'dashboard':
        const { DashboardPage } = await import('./pages/dashboard.js');
        return new DashboardPage();
      default:
        const { NotFoundPage } = await import('./pages/404.js');
        return new NotFoundPage();
    }
  }
};

// Conditional loading based on device capabilities
if ('IntersectionObserver' in window) {
  import('./lazy-loading.js').then(module => {
    module.initializeLazyLoading();
  });
} else {
  // Fallback for older browsers
  import('./legacy-loading.js');
}

// Feature-based loading
const loadAnalytics = () => {
  if (user.hasConsented) {
    import('./analytics.js').then(analytics => {
      analytics.initialize();
    });
  }
};

9.3. Image Optimization

Modern Image Formats

Use WebP and AVIF when supported

<picture>
  <!-- AVIF for modern browsers -->
  <source srcset="image.avif" type="image/avif">
  <!-- WebP for browsers that support it -->
  <source srcset="image.webp" type="image/webp">
  <!-- Fallback JPEG -->
  <img src="image.jpg" alt="Description" loading="lazy">
</picture>

<!-- Responsive images with srcset -->
<img
  src="image-400.jpg"
  srcset="
    image-400.jpg 400w,
    image-800.jpg 800w,
    image-1200.jpg 1200w,
    image-1600.jpg 1600w
  "
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  alt="Responsive image"
  loading="lazy"
>
Lazy Loading Implementation
class LazyImageLoader {
  constructor(options = {}) {
    this.options = {
      threshold: 0.1,
      rootMargin: '50px',
      ...options
    };

    this.observer = new IntersectionObserver(
      this.handleIntersection.bind(this),
      this.options
    );

    this.init();
  }

  init() {
    const lazyImages = document.querySelectorAll('img[data-src]');
    lazyImages.forEach(img => this.observer.observe(img));
  }

  handleIntersection(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        this.loadImage(entry.target);
        this.observer.unobserve(entry.target);
      }
    });
  }

  loadImage(img) {
    // Create new image to preload
    const imageLoader = new Image();

    imageLoader.onload = () => {
      // Replace placeholder with actual image
      img.src = img.dataset.src;
      img.classList.remove('lazy');
      img.classList.add('loaded');

      // Handle srcset for responsive images
      if (img.dataset.srcset) {
        img.srcset = img.dataset.srcset;
      }
    };

    imageLoader.onerror = () => {
      img.classList.add('error');
    };

    imageLoader.src = img.dataset.src;
  }
}

// Initialize lazy loading
new LazyImageLoader();

// Progressive image loading with blur effect
class ProgressiveImageLoader {
  constructor(container) {
    this.container = container;
    this.lowQualitySrc = container.dataset.lowQuality;
    this.highQualitySrc = container.dataset.highQuality;

    this.load();
  }

  load() {
    // Load low quality image first
    const lowQualityImg = new Image();
    lowQualityImg.onload = () => {
      this.container.style.backgroundImage = `url(${this.lowQualitySrc})`;
      this.container.classList.add('low-quality-loaded');

      // Start loading high quality image
      this.loadHighQuality();
    };
    lowQualityImg.src = this.lowQualitySrc;
  }

  loadHighQuality() {
    const highQualityImg = new Image();
    highQualityImg.onload = () => {
      this.container.style.backgroundImage = `url(${this.highQualitySrc})`;
      this.container.classList.remove('low-quality-loaded');
      this.container.classList.add('high-quality-loaded');
    };
    highQualityImg.src = this.highQualitySrc;
  }
}

9.4. JavaScript Optimization

Efficient DOM Manipulation

Minimize reflows and repaints

// Bad: Multiple DOM operations
function badUpdate(items) {
  const container = document.getElementById('container');

  // This causes multiple reflows
  items.forEach(item => {
    const element = document.createElement('div');
    element.textContent = item.name;
    element.style.color = item.color; // Causes repaint
    container.appendChild(element); // Causes reflow
  });
}

// Good: Batch DOM operations
function goodUpdate(items) {
  const fragment = document.createDocumentFragment();

  items.forEach(item => {
    const element = document.createElement('div');
    element.textContent = item.name;
    element.className = item.cssClass; // Use CSS classes instead
    fragment.appendChild(element);
  });

  // Single DOM operation
  document.getElementById('container').appendChild(fragment);
}

// Use CSS transforms for animations (GPU accelerated)
function animateElement(element, x, y) {
  // Bad: Changes layout
  // element.style.left = x + 'px';
  // element.style.top = y + 'px';

  // Good: Uses compositor
  element.style.transform = `translate3d(${x}px, ${y}px, 0)`;
}

// Virtual scrolling for large lists
class VirtualScroller {
  constructor(container, items, itemHeight) {
    this.container = container;
    this.items = items;
    this.itemHeight = itemHeight;
    this.visibleCount = Math.ceil(container.clientHeight / itemHeight) + 2;

    this.scrollTop = 0;
    this.startIndex = 0;

    this.setup();
  }

  setup() {
    // Create scrollable area
    this.scrollContainer = document.createElement('div');
    this.scrollContainer.style.height = this.items.length * this.itemHeight + 'px';

    // Create viewport
    this.viewport = document.createElement('div');
    this.viewport.style.height = '100%';
    this.viewport.style.overflow = 'auto';

    this.container.appendChild(this.viewport);
    this.viewport.appendChild(this.scrollContainer);

    // Handle scroll events
    this.viewport.addEventListener('scroll', () => {
      this.handleScroll();
    });

    this.render();
  }

  handleScroll() {
    const scrollTop = this.viewport.scrollTop;
    const newStartIndex = Math.floor(scrollTop / this.itemHeight);

    if (newStartIndex !== this.startIndex) {
      this.startIndex = newStartIndex;
      this.render();
    }
  }

  render() {
    // Clear existing items
    const existingItems = this.scrollContainer.querySelectorAll('.virtual-item');
    existingItems.forEach(item => item.remove());

    // Render visible items
    const endIndex = Math.min(
      this.startIndex + this.visibleCount,
      this.items.length
    );

    for (let i = this.startIndex; i < endIndex; i++) {
      const item = this.createItem(this.items[i], i);
      item.style.position = 'absolute';
      item.style.top = i * this.itemHeight + 'px';
      item.style.height = this.itemHeight + 'px';
      item.className = 'virtual-item';

      this.scrollContainer.appendChild(item);
    }
  }

  createItem(data, index) {
    const item = document.createElement('div');
    item.textContent = `Item ${index}: ${data.name}`;
    return item;
  }
}

9.5. Caching Strategies

HTTP Caching

Configure proper cache headers

# Static assets - cache for 1 year
/static/*
  Cache-Control: public, max-age=31536000, immutable

# HTML files - validate with server
/*.html
  Cache-Control: public, max-age=0, must-revalidate

# API responses - cache for 5 minutes
/api/*
  Cache-Control: public, max-age=300

# User-specific content - don't cache
/dashboard/*
  Cache-Control: private, no-cache, no-store, must-revalidate
Service Worker Caching
// Advanced caching strategies
const CACHE_NAME = 'app-cache-v1';
const RUNTIME_CACHE = 'runtime-cache';

class CacheManager {
  constructor() {
    this.strategies = {
      cacheFirst: this.cacheFirst.bind(this),
      networkFirst: this.networkFirst.bind(this),
      staleWhileRevalidate: this.staleWhileRevalidate.bind(this)
    };
  }

  async cacheFirst(request) {
    const cache = await caches.open(CACHE_NAME);
    const cached = await cache.match(request);

    if (cached) {
      return cached;
    }

    try {
      const response = await fetch(request);
      cache.put(request, response.clone());
      return response;
    } catch (error) {
      // Return offline fallback if available
      return await cache.match('/offline.html') ||
             new Response('Offline', { status: 503 });
    }
  }

  async networkFirst(request) {
    try {
      const response = await fetch(request);
      const cache = await caches.open(RUNTIME_CACHE);
      cache.put(request, response.clone());
      return response;
    } catch (error) {
      const cache = await caches.open(RUNTIME_CACHE);
      const cached = await cache.match(request);
      return cached || new Response('Network Error', { status: 503 });
    }
  }

  async staleWhileRevalidate(request) {
    const cache = await caches.open(RUNTIME_CACHE);
    const cached = await cache.match(request);

    // Start network request in background
    const networkRequest = fetch(request).then(response => {
      cache.put(request, response.clone());
      return response;
    });

    // Return cached version immediately if available
    return cached || networkRequest;
  }
}

// Memory caching for API responses
class MemoryCache {
  constructor(maxSize = 100, ttl = 300000) { // 5 minutes TTL
    this.cache = new Map();
    this.maxSize = maxSize;
    this.ttl = ttl;
  }

  set(key, value) {
    if (this.cache.size >= this.maxSize) {
      // Remove oldest entry
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }

    this.cache.set(key, {
      value,
      timestamp: Date.now()
    });
  }

  get(key) {
    const entry = this.cache.get(key);

    if (!entry) {
      return null;
    }

    // Check if expired
    if (Date.now() - entry.timestamp > this.ttl) {
      this.cache.delete(key);
      return null;
    }

    return entry.value;
  }

  clear() {
    this.cache.clear();
  }
}

// Usage
const apiCache = new MemoryCache();

async function cachedFetch(url, options = {}) {
  const cacheKey = url + JSON.stringify(options);

  // Check memory cache first
  const cached = apiCache.get(cacheKey);
  if (cached) {
    return Promise.resolve(new Response(JSON.stringify(cached)));
  }

  // Fetch from network
  const response = await fetch(url, options);
  const data = await response.json();

  // Cache the response
  apiCache.set(cacheKey, data);

  return new Response(JSON.stringify(data));
}

9.6. Performance Monitoring

Web Performance APIs
// Performance monitoring
class PerformanceMonitor {
  constructor() {
    this.metrics = {};
    this.init();
  }

  init() {
    // Core Web Vitals
    this.measureCWV();

    // Navigation timing
    this.measureNavigation();

    // Resource timing
    this.measureResources();

    // Custom metrics
    this.measureCustom();
  }

  measureCWV() {
    // Largest Contentful Paint
    new PerformanceObserver((list) => {
      const entries = list.getEntries();
      const lastEntry = entries[entries.length - 1];

      this.metrics.lcp = lastEntry.startTime;
      this.sendMetric('lcp', lastEntry.startTime);
    }).observe({ type: 'largest-contentful-paint', buffered: true });

    // First Input Delay
    new PerformanceObserver((list) => {
      const entries = list.getEntries();
      entries.forEach(entry => {
        this.metrics.fid = entry.processingStart - entry.startTime;
        this.sendMetric('fid', entry.processingStart - entry.startTime);
      });
    }).observe({ type: 'first-input', buffered: true });

    // Cumulative Layout Shift
    let clsScore = 0;
    new PerformanceObserver((list) => {
      const entries = list.getEntries();
      entries.forEach(entry => {
        if (!entry.hadRecentInput) {
          clsScore += entry.value;
        }
      });

      this.metrics.cls = clsScore;
      this.sendMetric('cls', clsScore);
    }).observe({ type: 'layout-shift', buffered: true });
  }

  measureNavigation() {
    const navigation = performance.getEntriesByType('navigation')[0];

    this.metrics.ttfb = navigation.responseStart - navigation.requestStart;
    this.metrics.domLoad = navigation.domContentLoadedEventEnd - navigation.navigationStart;
    this.metrics.windowLoad = navigation.loadEventEnd - navigation.navigationStart;

    this.sendMetrics({
      ttfb: this.metrics.ttfb,
      domLoad: this.metrics.domLoad,
      windowLoad: this.metrics.windowLoad
    });
  }

  measureResources() {
    const resources = performance.getEntriesByType('resource');

    resources.forEach(resource => {
      if (resource.name.includes('.js') || resource.name.includes('.css')) {
        this.sendMetric('resource_load', {
          name: resource.name,
          duration: resource.duration,
          size: resource.transferSize
        });
      }
    });
  }

  measureCustom() {
    // Time to Interactive (custom implementation)
    this.measureTimeToInteractive();

    // Bundle size tracking
    this.trackBundleSize();
  }

  measureTimeToInteractive() {
    let tti = 0;

    // Simplified TTI calculation
    const observer = new PerformanceObserver((list) => {
      const entries = list.getEntries();
      const longTasks = entries.filter(entry => entry.duration > 50);

      if (longTasks.length === 0) {
        tti = performance.now();
        this.sendMetric('tti', tti);
        observer.disconnect();
      }
    });

    observer.observe({ type: 'longtask', buffered: true });
  }

  trackBundleSize() {
    const scripts = document.querySelectorAll('script[src]');
    let totalSize = 0;

    scripts.forEach(script => {
      const resource = performance.getEntriesByName(script.src)[0];
      if (resource) {
        totalSize += resource.transferSize;
      }
    });

    this.sendMetric('bundle_size', totalSize);
  }

  sendMetric(name, value) {
    // Send to analytics service
    if (navigator.sendBeacon) {
      navigator.sendBeacon('/api/metrics', JSON.stringify({
        metric: name,
        value: value,
        timestamp: Date.now(),
        url: location.href
      }));
    }
  }

  sendMetrics(metrics) {
    Object.entries(metrics).forEach(([name, value]) => {
      this.sendMetric(name, value);
    });
  }
}

// Initialize performance monitoring
new PerformanceMonitor();

// Real User Monitoring (RUM)
class RUMCollector {
  constructor() {
    this.data = {
      connection: this.getConnectionInfo(),
      device: this.getDeviceInfo(),
      timing: {},
      errors: []
    };

    this.collectErrors();
  }

  getConnectionInfo() {
    const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;

    return {
      effectiveType: connection?.effectiveType,
      downlink: connection?.downlink,
      rtt: connection?.rtt,
      saveData: connection?.saveData
    };
  }

  getDeviceInfo() {
    return {
      userAgent: navigator.userAgent,
      memory: navigator.deviceMemory,
      cores: navigator.hardwareConcurrency,
      platform: navigator.platform,
      viewport: {
        width: window.innerWidth,
        height: window.innerHeight
      }
    };
  }

  collectErrors() {
    window.addEventListener('error', (event) => {
      this.data.errors.push({
        message: event.message,
        filename: event.filename,
        line: event.lineno,
        column: event.colno,
        timestamp: Date.now()
      });
    });

    window.addEventListener('unhandledrejection', (event) => {
      this.data.errors.push({
        message: event.reason?.message || 'Unhandled Promise Rejection',
        timestamp: Date.now()
      });
    });
  }

  collect() {
    return {
      ...this.data,
      timing: this.getTimingData()
    };
  }

  getTimingData() {
    const navigation = performance.getEntriesByType('navigation')[0];
    const paint = performance.getEntriesByType('paint');

    return {
      navigation: {
        redirectTime: navigation.redirectEnd - navigation.redirectStart,
        dnsTime: navigation.domainLookupEnd - navigation.domainLookupStart,
        connectTime: navigation.connectEnd - navigation.connectStart,
        responseTime: navigation.responseEnd - navigation.responseStart,
        domTime: navigation.domContentLoadedEventEnd - navigation.navigationStart,
        loadTime: navigation.loadEventEnd - navigation.navigationStart
      },
      paint: {
        fcp: paint.find(entry => entry.name === 'first-contentful-paint')?.startTime,
        fp: paint.find(entry => entry.name === 'first-paint')?.startTime
      }
    };
  }
}

9.7. Performance Testing Tools

Lighthouse

Automated auditing for performance, accessibility, and best practices

WebPageTest

Detailed performance analysis with waterfall charts

Chrome DevTools

Performance profiling and debugging

Real User Monitoring

Track actual user experience metrics

Synthetic Monitoring

Automated performance testing from multiple locations

Key optimization strategies: - Minimize HTTP requests - Optimize images and use modern formats - Implement efficient caching strategies - Use CDNs for global content delivery - Minimize and compress JavaScript/CSS - Implement lazy loading for non-critical resources - Optimize database queries and server response times - Use performance monitoring to track improvements

10. Links and Literature