Lesson 11-Front-end Performance Optimization Basics

Resource Loading Optimization

Resource Compression and Merging

CSS/JS Compression Techniques:

  1. Compression Principles:
    • Remove whitespace, comments, and line breaks.
    • Shorten variable and function names (obfuscation).
    • Eliminate dead code and unused code.
  2. Toolchain Options:
    • Webpack: TerserPlugin (JavaScript), CssMinimizerPlugin (CSS).
    • Rollup: Terser plugin.
    • Vite: Built-in Terser compression.
  3. Compression Configuration Example:
// webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: true,
        terserOptions: {
          compress: { drop_console: true },
          mangle: true
        }
      }),
      new CssMinimizerPlugin()
    ]
  }
};

Image Optimization Strategies:

  1. Format Selection Guide:
    • JPEG: Suitable for photographic images.
    • PNG: Ideal for images requiring transparency.
    • WebP: Modern format with better compression rates.
    • AVIF: Next-generation format with higher compression efficiency.
  2. Recommended Compression Tools:
    • Squoosh: Google’s online image compression tool.
    • ImageOptim: Image optimization tool for Mac.
    • Sharp: Node.js image processing library.
  3. Responsive Image Implementation:
<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="Example image">
</picture>

Caching Strategies

Cache Types Comparison:

Cache TypeDescriptionUse CaseExample
Strong CacheUses cache directly without server requestsInfrequently changing static resourcesCache-Control: max-age=31536000
Negotiated CacheValidates resource changes with the serverFrequently updated resourcesETag/Last-Modified
Service WorkerFully developer-controlled cacheOffline apps, PWAsCustom caching logic

Service Worker Cache Example:

// sw.js
const CACHE_NAME = 'v1';
const ASSETS = [
  '/index.html',
  '/styles/main.css',
  '/scripts/main.js'
];

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

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

Cache Update Strategies:

  1. Versioned Filenames: main.[hash].js
  2. Cache Clearing: Periodically clear old caches.
  3. Cache Preheating: Preload critical resources.

Resource Preloading

Preloading Techniques Explained:

TechniquePurposePriorityUse Case
preloadPreload critical resources for the current pageHighCritical CSS/JS
prefetchPreload resources likely needed in the futureLowNext-page resources
preconnectEstablish connections in advanceMediumThird-party domains
dns-prefetchPre-resolve DNSLowCross-domain resources

Implementation Example:

<!-- Critical resource preloading -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="main.js" as="script">

<!-- Predictive prefetching -->
<link rel="prefetch" href="next-page.js" as="script">

<!-- Connection optimization -->
<link rel="preconnect" href="https://api.example.com">
<link rel="dns-prefetch" href="https://cdn.example.com">

Dynamic Preloading Strategies:

// Preloading based on user behavior
document.addEventListener('mousemove', (e) => {
  if (e.clientX > window.innerWidth - 100) {
    // User may scroll, preload next page
    import(/* webpackPrefetch: true */ './next-page');
  }
});

// Route-based preloading
const routes = [
  {
    path: '/dashboard',
    component: () => import(/* webpackPrefetch: true */ './Dashboard')
  }
];

Lazy Loading and On-Demand Loading

Image Lazy Loading Implementation:

  1. Intersection Observer API:
const lazyImages = document.querySelectorAll('img[data-src]');

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      observer.unobserve(img);
    }
  });
});

lazyImages.forEach(img => observer.observe(img));
  1. Traditional Scroll Event Implementation:
function lazyLoad() {
  const images = document.querySelectorAll('img[data-src]');
  images.forEach(img => {
    if (img.getBoundingClientRect().top < window.innerHeight) {
      img.src = img.dataset.src;
    }
  });
}

window.addEventListener('scroll', throttle(lazyLoad, 200));

Route Lazy Loading:

// React.lazy + Suspense
const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

// Vue async component
const AsyncComponent = () => ({
  component: import('./AsyncComponent.vue'),
  loading: LoadingComponent,
  error: ErrorComponent,
  delay: 200,
  timeout: 3000
});

Resource Prioritization and Scheduling

Resource Hints Explained:

  1. preload: High-priority preload for current page resources.
  2. prefetch: Low-priority preload for future resources.
  3. preconnect: Pre-establish connections (DNS, TLS handshake, etc.).
  4. dns-prefetch: Pre-resolve DNS only.

Priority Control Example:

<!-- High-priority resources -->
<link rel="preload" href="main.css" as="style" importance="high">
<link rel="preload" href="main.js" as="script" importance="high">

<!-- Low-priority resources -->
<link rel="prefetch" href="next-page.js" as="script" importance="low">

Resource Loading Order Optimization:

  1. Inline Critical CSS: Avoid render blocking.
  2. Asynchronous Non-Critical JS: Use async/defer.
  3. Font Preloading: <link rel="preload" href="font.woff2" as="font">

Rendering Performance Optimization

Critical Rendering Path Optimization

CRP Optimization Steps:

  1. Reduce Render-Blocking Resources:
    • Inline critical CSS.
    • Asynchronously load non-critical JS.
  2. Optimize HTML Structure:
    • Simplify DOM tree depth.
    • Avoid deep nesting.
  3. CRP Analysis Tools:
    • Chrome DevTools Coverage tool.
    • WebPageTest First Meaningful Paint analysis.

Optimization Example:

<!-- Before optimization -->
<head>
  <link rel="stylesheet" href="all.css">
  <script src="analytics.js"></script>
</head>

<!-- After optimization -->
<head>
  <style>/* Inline critical CSS */</style>
  <link rel="preload" href="all.css" as="style" onload="this.rel='stylesheet'">
  <script defer src="analytics.js"></script>
</head>

CSS Optimization

Avoiding Repaints and Reflows:

  1. Repaint: Changes to element appearance without affecting layout.
  2. Reflow: Changes to element size or position affecting layout.

Optimization Strategies:

  1. Use transform and opacity: Trigger GPU acceleration.
  2. Avoid Frequent Style Changes: Batch style updates.
  3. Use will-change: Hint to the browser about upcoming changes.

CSS Performance Pitfalls:

/* Bad: Triggers reflow */
.box {
  width: 100px;
  height: 100px;
  transition: width 0.3s, height 0.3s;
}

/* Good: Triggers compositing only */
.box {
  width: 100px;
  height: 100px;
  transform: scale(1);
  transition: transform 0.3s;
}

JavaScript Execution Optimization

Reducing Main Thread Blocking:

  1. Web Workers: Offload computationally intensive tasks to background threads.
  2. requestIdleCallback: Execute tasks during idle time.
  3. Task Chunking: Break large tasks into smaller ones.

Optimization Example:

// Use Web Worker for large data processing
const worker = new Worker('data-processor.js');
worker.postMessage(largeData);
worker.onmessage = (e) => {
  // Process result
};

// Use requestIdleCallback
function processTask(deadline) {
  while (deadline.timeRemaining() > 0 && tasks.length > 0) {
    const task = tasks.pop();
    task();
  }
  if (tasks.length > 0) {
    requestIdleCallback(processTask);
  }
}
requestIdleCallback(processTask);

Event Handling Optimization:

  1. Event Delegation: Reduce the number of event listeners.
  2. Debouncing and Throttling: Control event trigger frequency.
  3. Passive Event Listeners: Improve scrolling performance.

Virtual DOM and Diff Algorithm Optimization

Virtual DOM Principles:

  1. Virtual DOM Tree: JavaScript object representation of the DOM structure.
  2. Diff Algorithm: Compares differences between old and new virtual DOM trees.
  3. Patch Process: Applies differences to the real DOM.

Optimization Strategies:

  1. Use Keys Wisely: Help the Diff algorithm identify nodes efficiently.
  2. Avoid Unnecessary Re-renders:
    • Use React.memo/PureComponent.
    • Implement shouldComponentUpdate.
  3. Batch Updates: Reduce DOM operations.

Diff Algorithm Optimization Example:

// Bad: Creates new array on every render
function List({ items }) {
  return (
    <ul>
      {items.map(item => (
        <ListItem key={item.id} item={item} />
      ))}
    </ul>
  );
}

// Good: Avoids inline functions and objects
const MemoizedListItem = React.memo(ListItem);

function List({ items }) {
  return (
    <ul>
      {items.map(item => (
        <MemoizedListItem 
          key={item.id} 
          item={item} 
          onClick={handleClick} // Avoid inline functions
        />
      ))}
    </ul>
  );
}

GPU Acceleration and Compositing Layer Optimization

GPU Acceleration Techniques:

  1. transform and opacity: Trigger GPU acceleration.
  2. will-change: Hint to the browser about upcoming changes.
  3. translateZ(0): Force creation of a separate layer (deprecated).

Compositing Layer Management:

  1. Use will-change Judiciously:
.animated-element {
  will-change: transform, opacity;
}
  1. Avoid Excessive Compositing Layers:
    • Inspect with chrome://flags/#composited-layer-borders.
    • Analyze using the Layers panel.
  2. Animation Performance Optimization:
    • Use requestAnimationFrame.
    • Avoid reflows during animations.

Network Transmission Optimization

HTTP/2 and HTTP/3 Features

HTTP/2 Core Features:

  1. Multiplexing: Parallel multiple requests over a single connection.
  2. Header Compression: HPACK algorithm reduces overhead.
  3. Server Push: Proactively push resources to the client.

HTTP/3 New Features:

  1. QUIC Protocol: Resolves TCP head-of-line blocking.
  2. Improved Congestion Control: Faster connection establishment.
  3. Better Mobile Network Support: Reduced packet loss impact.

Protocol Upgrade Strategies:

  1. Server Configuration:
    • Enable HTTP/2 (nginx: http2 on;).
    • Prepare for HTTP/3 (requires QUIC support).
  2. Client Compatibility:
    • Modern browsers fully support HTTP/2.
    • HTTP/3 requires specific client support.

CDN Acceleration and Edge Computing

CDN Principles:

  1. Content Delivery Network: Globally distributed server nodes.
  2. Intelligent Routing: Selects the nearest node to serve content.
  3. Caching Strategy: Caches static resources.

Edge Computing Applications:

  1. Edge Rendering: Generate HTML at edge nodes.
  2. Edge Caching: Cache dynamic content.
  3. Edge Functions: Execute simple logic at the edge.

CDN Configuration Example:

# nginx CDN configuration example
server {
  listen 80;
  server_name example.com;

  location /static/ {
    alias /var/www/static/;
    expires 1y;
    add_header Cache-Control "public";
  }

  location / {
    proxy_pass http://backend;
  }
}

Data Compression and Encoding

Compression Algorithm Comparison:

AlgorithmCompression RateSpeedCPU UsageUse Case
GzipModerateFastLowGeneral
BrotliHighMediumMediumText resources
ZstandardHighFastMediumGeneral

Server Configuration Example:

# nginx Gzip configuration
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 6;
gzip_min_length 256;

# Brotli configuration (requires additional module)
brotli on;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

Client Detection:

// Detect supported compression algorithms
const acceptEncoding = navigator.userAgent.match(/Accept-Encoding:\s*(.*)/i)[1];
const supportsBrotli = acceptEncoding.includes('br');
const supportsGzip = acceptEncoding.includes('gzip');

Reducing Network Requests

Resource Merging Strategies:

  1. CSS/JS Merging: Reduce HTTP requests.
  2. Sprite Sheets: Combine multiple small icons.
  3. Inline Critical Resources: Avoid render blocking.

Inline Resource Example:

<!-- Inline critical CSS -->
<style>
  /* Critical CSS content */
</style>

<!-- Inline small images (Base64) -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." alt="Small icon">

Resource Merging Considerations for HTTP/2:

  1. Trade-offs:
    • HTTP/2 allows efficient parallel loading of multiple small files.
    • Excessive merging may lead to cache invalidation.
  2. Recommended Strategies:
    • Inline critical CSS.
    • Load non-critical CSS/JS on demand.
    • Keep large resources as separate files.

Network Latency and Packet Loss Optimization

Latency Optimization Techniques:

  1. Preconnect: <link rel="preconnect">
  2. Preload: <link rel="preload">
  3. DNS Prefetch: <link rel="dns-prefetch">

Packet Loss Optimization Strategies:

  1. QUIC Protocol: Foundation of HTTP/3.
  2. Forward Error Correction (FEC): Send redundant data preemptively.
  3. Multipath Transmission: Use multiple network connections simultaneously.

Network Status Detection:

// Detect network connection type
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (connection) {
  console.log('Network type:', connection.effectiveType);
  console.log('RTT:', connection.rtt);
  console.log('Downlink speed:', connection.downlink + 'Mb/s');
}

// Monitor network changes
connection.addEventListener('change', () => {
  // Adjust resource loading strategy
});

Offline Handling Solutions:

  1. Service Worker Caching: Enable offline access to core functionality.
  2. Local Storage: Save critical data.
  3. Retry Mechanism: Automatically retry when the network recovers.

Summary

Frontend performance optimization is a systematic process that requires comprehensive improvements across resource loading, rendering performance, and network transmission. Key aspects of modern web application performance optimization include:

  1. Reducing Critical Rendering Path Blocking: Through code splitting, lazy loading, and other techniques.
  2. Optimizing Resource Loading: Using caching, preloading, and compression effectively.
  3. Improving Rendering Efficiency: Avoiding repaints and reflows, optimizing CSS and JavaScript execution.
  4. Adapting to Network Conditions: Tailoring resource delivery strategies for varying network environments.
  5. Continuous Monitoring and Analysis: Leveraging performance tools to track optimization results.

By systematically applying these optimization techniques, web application performance can be significantly enhanced, improving user experience and achieving business objectives.

Share your love