Skip to main content

Best Practices

Modern web development standards based on Lighthouse best practices audits. Covers security, browser compatibility, and code quality patterns.

Security

HTTPS Everywhere

<img src="http://example.com/image.jpg">
<script src="http://cdn.example.com/script.js"></script>
HSTS Header:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Content Security Policy (CSP)

<!-- Basic CSP via meta tag -->
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; 
               script-src 'self' https://trusted-cdn.com; 
               style-src 'self' 'unsafe-inline';
               img-src 'self' data: https:;
               connect-src 'self' https://api.example.com;">

Security Headers

# Prevent clickjacking
X-Frame-Options: DENY

# Prevent MIME type sniffing
X-Content-Type-Options: nosniff

# Enable XSS filter (legacy browsers)
X-XSS-Protection: 1; mode=block

# Control referrer information
Referrer-Policy: strict-origin-when-cross-origin

# Permissions policy (formerly Feature-Policy)
Permissions-Policy: geolocation=(), microphone=(), camera=()

No Vulnerable Libraries

# Check for vulnerabilities
npm audit
yarn audit

# Auto-fix when possible
npm audit fix

# Check specific package
npm ls lodash
Keep dependencies updated:
// package.json
{
  "scripts": {
    "audit": "npm audit --audit-level=moderate",
    "update": "npm update && npm audit fix"
  }
}
Known vulnerable patterns to avoid:
Object.assign(target, userInput);
_.merge(target, userInput);

Input Sanitization

element.innerHTML = userInput;
document.write(userInput);

Secure Cookies

document.cookie = "session=abc123";

Browser Compatibility

Doctype Declaration

<HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">

Character Encoding

<html>
<head>
  <title>Page</title>
  <meta charset="UTF-8">
</head>

Viewport Meta Tag

<head>
  <title>Page</title>
</head>

Feature Detection

if (navigator.userAgent.includes('Chrome')) {
  // Chrome-specific code
}

Polyfills (When Needed)

<!-- Load polyfills conditionally -->
<script>
  if (!('fetch' in window)) {
    document.write('<script src="/polyfills/fetch.js"><\/script>');
  }
</script>

<!-- Or use polyfill.io -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=fetch,IntersectionObserver"></script>

Deprecated APIs

Avoid These

// ❌ document.write (blocks parsing)
document.write('<script src="..."></script>');

// ✅ Dynamic script loading
const script = document.createElement('script');
script.src = '...';
document.head.appendChild(script);

Event Listener Passive

element.addEventListener('touchstart', handler);
element.addEventListener('wheel', handler);

Console & Errors

No Console Errors

console.log('Debug info'); // Remove in production
throw new Error('Unhandled'); // Catch all errors

Error Boundaries (React)

class ErrorBoundary extends React.Component {
  state = { hasError: false };
  
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  
  componentDidCatch(error, info) {
    errorTracker.captureException(error, { extra: info });
  }
  
  render() {
    if (this.state.hasError) {
      return <FallbackUI />;
    }
    return this.props.children;
  }
}

// Usage
<ErrorBoundary>
  <App />
</ErrorBoundary>

Global Error Handler

// Catch unhandled errors
window.addEventListener('error', (event) => {
  errorTracker.captureException(event.error);
});

// Catch unhandled promise rejections
window.addEventListener('unhandledrejection', (event) => {
  errorTracker.captureException(event.reason);
});

Source Maps

Production Configuration

// webpack.config.js
module.exports = {
  devtool: 'source-map', // Exposes source code
};

Performance Best Practices

Avoid Blocking Patterns

<script src="heavy-library.js"></script>
@import url('other-styles.css');

Efficient Event Handlers

items.forEach(item => {
  item.addEventListener('click', handleClick);
});

Memory Management

const handler = () => { /* ... */ };
window.addEventListener('resize', handler);

Code Quality

Valid HTML

<div id="header">
<div id="header"> <!-- Duplicate ID -->

<ul>
  <div>Item</div> <!-- Invalid child -->
</ul>

<a href="/"><button>Click</button></a> <!-- Invalid nesting -->

Semantic HTML

<div class="header">
  <div class="nav">
    <div class="nav-item">Home</div>
  </div>
</div>
<div class="main">
  <div class="article">
    <div class="title">Headline</div>
  </div>
</div>

Image Aspect Ratios

<img src="photo.jpg" width="300" height="100">
<!-- If actual ratio is 4:3, this squishes the image -->

Permissions & Privacy

Request Permissions Properly

navigator.geolocation.getCurrentPosition(success, error);

Permissions Policy

<!-- Restrict powerful features -->
<meta http-equiv="Permissions-Policy" 
      content="geolocation=(), camera=(), microphone=()">

<!-- Or allow for specific origins -->
<meta http-equiv="Permissions-Policy" 
      content="geolocation=(self 'https://maps.example.com')">

Audit Checklist

Security (Critical)

  • HTTPS enabled, no mixed content
  • No vulnerable dependencies (npm audit)
  • CSP headers configured
  • Security headers present
  • No exposed source maps

Compatibility

  • Valid HTML5 doctype
  • Charset declared first in head
  • Viewport meta tag present
  • No deprecated APIs used
  • Passive event listeners for scroll/touch

Code Quality

  • No console errors
  • Valid HTML (no duplicate IDs)
  • Semantic HTML elements used
  • Proper error handling
  • Memory cleanup in components

UX

  • No intrusive interstitials
  • Permission requests in context
  • Clear error messages
  • Appropriate image aspect ratios

Tools

| Tool | Purpose | |------|---------|| | npm audit | Dependency vulnerabilities | | SecurityHeaders.com | Header analysis | | W3C Validator | HTML validation | | Lighthouse | Best practices audit | | Observatory | Security scan |

External Resources

Web Quality Audit

For comprehensive best practices audit as part of overall quality

Build docs developers (and LLMs) love