mcpField
B
best-practices

best-practices

github.com/tech-leads-club开发7.1k265 次安装4 天前更新
代码仓库

关于 best-practices

这项 Web 开发参考技能基于 Lighthouse 最佳实践审计,面向需要检查网站安全性、浏览器兼容性、性能和代码质量的开发者,并提供指导与审查清单。

主要功能

  1. 01安全标头与输入安全
  2. 02浏览器兼容性指导
  3. 03过时 API 的替代方案
  4. 04错误处理与源映射
  5. 05性能和内存管理实践
  6. 06审计清单与工具

适用场景

  1. 01检查 Web 应用安全性
  2. 02核对浏览器兼容性
  3. 03减少生产环境错误
  4. 04审计性能与代码质量

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tech-leads-club/agent-skills --skill best-practices

安装后在 Claude Code 中输入/best-practices确认已加载。

详细介绍

最佳实践

基于 Lighthouse 最佳实践审计的现代 Web 开发标准。涵盖安全性、浏览器兼容性和代码质量模式。

安全性

全面使用 HTTPS

强制使用 HTTPS:


<img src="http://example.com/image.jpg" />
<script src="http://cdn.example.com/script.js"></script>


<img src="https://example.com/image.jpg" />
<script src="https://cdn.example.com/script.js"></script>


<img src="//example.com/image.jpg" />

HSTS 标头:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
内容安全策略(CSP)

<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;"
/>


CSP 标头(推荐):

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';

在内联脚本中使用 nonce:

<script nonce="abc123">
  // This inline script is allowed
</script>
安全标头
# 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=()
避免使用存在漏洞的库
# Check for vulnerabilities
npm audit
yarn audit

# Auto-fix when possible
npm audit fix

# Check specific package
npm ls lodash

保持依赖项更新:

// package.json
{
  "scripts": {
    "audit": "npm audit --audit-level=moderate",
    "update": "npm update && npm audit fix"
  }
}

应避免的已知漏洞模式:

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

// ✅ Safer alternatives
const safeData = JSON.parse(JSON.stringify(userInput))
输入清理
// ❌ 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)
安全 Cookie
// ❌ Insecure cookie
document.cookie = "session=abc123";

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

浏览器兼容性

Doctype 声明

<html lang="en">
  <head>
    <title>Page</title>
  </head>
  <body></body>
</html>


<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Page</title>
  </head>
  <body></body>
</html>
字符编码

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Page</title>
    <meta charset="UTF-8" />
  </head>
  <body></body>
</html>


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Page</title>
  </head>
  <body></body>
</html>
Viewport meta 标签

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


<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Page</title>
</head>
功能检测
// ❌ 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;
  }
}
Polyfill(需要时)

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


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

已弃用的 API

避免使用以下 API
// ❌ document.write (blocks parsing)
document.write('<script src="..."></script>');

// ✅ 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)
<html manifest="cache.manifest">

// ✅ Service Workers
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}
事件监听器的 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 })

控制台与错误

不出现控制台错误
// ❌ 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.')
}
错误边界(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>
全局错误处理程序
// Catch unhandled errors
window.addEventListener('error', (event) => {
  errorTracker.captureException(event.error)
})

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

Source map

生产环境配置
// ❌ 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',
}

性能最佳实践

避免阻塞模式
// ❌ Blocking script
<script src="heavy-library.js"></script>

// ✅ Deferred script
<script defer src="heavy-library.js"></script>

// ❌ Blocking CSS import
@import url('other-styles.css');

// ✅ Link tags (parallel loading)
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="other-styles.css">
高效的事件处理程序
// ❌ 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 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()

代码质量

有效的 HTML

<div id="header">
  <div id="header">
    
  </div>

  <ul>
    <div>Item</div>
    
  </ul>

  <a href="/"><button>Click</button></a>
  
</div>


<header id="site-header"></header>

<ul>
  <li>Item</li>
</ul>

<a href="/" class="button">Click</a>
语义化 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>


<header>
  <nav>
    <a href="/">Home</a>
  </nav>
</header>
<main>
  <article>
    <h1>Headline</h1>
  </article>
</main>
图片宽高比

<img src="photo.jpg" width="300" height="100" />



<img src="photo.jpg" width="300" height="225" />



<img src="photo.jpg" style="width: 300px; height: 200px; object-fit: cover;" />

权限与隐私

正确请求权限
// ❌ Request on page load (bad UX, often denied)
navigator.geolocation.getCurrentPosition(success, error)

// ✅ Request in context, after user action
findNearbyButton.addEventListener('click', async () => {
  // Explain why you need it
  if (await showPermissionExplanation()) {
    navigator.geolocation.getCurrentPosition(success, error)
  }
})
权限策略

<meta http-equiv="Permissions-Policy" content="geolocation=(), camera=(), microphone=()" />


<meta http-equiv="Permissions-Policy" content="geolocation=(self 'https://maps.example.com')" />

审计清单

安全性(关键)
  • 已启用 HTTPS,且没有混合内容
  • 没有存在漏洞的依赖项(npm audit)
  • 已配置 CSP 标头
  • 存在安全标头
  • 没有暴露 Source map
兼容性
  • 使用有效的 HTML5 doctype
  • 在 head 中最先声明字符集
  • 存在 Viewport meta 标签
  • 未使用已弃用的 API
  • 滚动/触摸事件使用 passive 监听器
代码质量
  • 没有控制台错误
  • HTML 有效(没有重复的 ID)
  • 使用语义化 HTML 元素
  • 正确处理错误
  • 清理组件中的内存
用户体验
  • 没有侵入式插页
  • 在适当的场景请求权限
  • 错误消息清晰
  • 图片宽高比适当

工具

工具用途
npm audit依赖项漏洞
SecurityHeaders.com标头分析
W3C ValidatorHTML 验证
Lighthouse最佳实践审计
Observatory安全扫描

参考资料

评论

支持 Markdown