best-practices

安装量: 3.1K
排名: #709

安装

npx skills add https://github.com/addyosmani/web-quality-skills --skill best-practices

Best practices

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

Security HTTPS everywhere

Enforce HTTPS:

HSTS Header:

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

Content Security Policy (CSP)

CSP Header (recommended):

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123' https://trusted.com; style-src 'self' 'nonce-abc123'; img-src 'self' data: https:; connect-src 'self' https://api.example.com; frame-ancestors 'self'; base-uri 'self'; form-action 'self';

Using nonces for inline scripts:

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:

// ❌ Prototype pollution vulnerable patterns Object.assign(target, userInput); _.merge(target, userInput);

// ✅ Safer alternatives const safeData = JSON.parse(JSON.stringify(userInput));

Input sanitization // ❌ XSS vulnerable element.innerHTML = userInput; document.write(userInput);

// ✅ Safe text content element.textContent = userInput;

// ✅ If HTML needed, sanitize import DOMPurify from 'dompurify'; element.innerHTML = DOMPurify.sanitize(userInput);

Secure cookies // ❌ Insecure cookie document.cookie = "session=abc123";

// ✅ Secure cookie (server-side) Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Strict; Path=/

Browser compatibility Doctype declaration

Character encoding Page Page Viewport meta tag Page Page Feature detection // ❌ Browser detection (brittle) if (navigator.userAgent.includes('Chrome')) { // Chrome-specific code } // ✅ Feature detection if ('IntersectionObserver' in window) { // Use IntersectionObserver } else { // Fallback } // ✅ Using @supports in CSS @supports (display: grid) { .container { display: grid; } } @supports not (display: grid) { .container { display: flex; } } Polyfills (when needed) Deprecated APIs Avoid these // ❌ document.write (blocks parsing) document.write(''); // ✅ Dynamic script loading const script = document.createElement('script'); script.src = '...'; document.head.appendChild(script); // ❌ Synchronous XHR (blocks main thread) const xhr = new XMLHttpRequest(); xhr.open('GET', url, false); // false = synchronous // ✅ Async fetch const response = await fetch(url); // ❌ Application Cache (deprecated) // ✅ Service Workers if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js'); } Event listener passive // ❌ Non-passive touch/wheel (may block scrolling) element.addEventListener('touchstart', handler); element.addEventListener('wheel', handler); // ✅ Passive listeners (allows smooth scrolling) element.addEventListener('touchstart', handler, { passive: true }); element.addEventListener('wheel', handler, { passive: true }); // ✅ If you need preventDefault, be explicit element.addEventListener('touchstart', handler, { passive: false }); Console & errors No console errors // ❌ Errors in production console.log('Debug info'); // Remove in production throw new Error('Unhandled'); // Catch all errors // ✅ Proper error handling try { riskyOperation(); } catch (error) { // Log to error tracking service errorTracker.captureException(error); // Show user-friendly message showErrorMessage('Something went wrong. Please try again.'); } 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 ; } return this.props.children; } } // Usage 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 // ❌ Source maps exposed in production // webpack.config.js module.exports = { devtool: 'source-map', // Exposes source code }; // ✅ Hidden source maps (uploaded to error tracker) module.exports = { devtool: 'hidden-source-map', }; // ✅ Or no source maps in production module.exports = { devtool: process.env.NODE_ENV === 'production' ? false : 'source-map', }; Performance best practices Avoid blocking patterns // ❌ Blocking script // ✅ Deferred script // ❌ Blocking CSS import @import url('other-styles.css'); // ✅ Link tags (parallel loading) Efficient event handlers // ❌ Handler on every element items.forEach(item => { item.addEventListener('click', handleClick); }); // ✅ Event delegation container.addEventListener('click', (e) => { if (e.target.matches('.item')) { handleClick(e); } }); Memory management // ❌ Memory leak (never removed) const handler = () => { /* ... */ }; window.addEventListener('resize', handler); // ✅ Cleanup when done const handler = () => { /* ... */ }; window.addEventListener('resize', handler); // Later, when component unmounts: window.removeEventListener('resize', handler); // ✅ Using AbortController const controller = new AbortController(); window.addEventListener('resize', handler, { signal: controller.signal }); // Cleanup: controller.abort(); Code quality Valid HTML
返回排行榜