代碼優化是提升網站加載速度和運行效率的核心環節,需要從 “精簡體積、減少阻塞、提升執行效率” 三個維度入手,結合前端和后端代碼特性制定針對性方案。以下是可直接落地的具體操作方法,附實操示例。
- 刪除無效代碼:清理注釋、空行、重復的 meta 標簽(如多個
<meta name="viewport"> )、未使用的 class/id;
- 簡化 DOM 結構:避免嵌套過深(建議不超過 5 層,如
<div><div><div><div><p>...</p></div></div></div></div> 需簡化),減少瀏覽器渲染時的回流(Reflow)成本;
- 使用語義化標簽:用
<header><nav><main><footer> 替代大量<div> ,既減少代碼量,又提升解析效率(瀏覽器對語義標簽的解析更高效)。
<div class="header">
<div class="logo">...</div>
<div class="nav">
<div class="nav-item">首頁</div>
<div class="nav-item">產品</div>
</div>
</div>
優化后(語義化 + 減少嵌套):
<header>
<div class="logo">...</div>
<nav>
<span class="nav-item">首頁</span>
<span class="nav-item">產品</span>
</nav>
</header>
- 合并 + 壓縮 CSS:將多個 CSS 文件(如
base.css 、home.css 、product.css )合并為 1 個,并用工具(如 CSSNano)壓縮(去除空格、簡化選擇器);
- 提取關鍵 CSS:將首屏渲染必需的 CSS(如導航、Banner 樣式)內嵌到
<head> 中,非首屏 CSS(如頁腳、隱藏模塊)通過<link rel="preload"> 異步加載,避免阻塞頁面渲染;
- 優化選擇器:避免復雜選擇器(如
div:nth-child(2) > .class ~ span ),改用簡單類名(如.specific-class ),瀏覽器匹配選擇器的效率可提升 30% 以上;
- 刪除未使用 CSS:通過 Chrome 開發者工具的 “Coverage” 面板(按 F12 → More Tools → Coverage)檢測未使用的 CSS 代碼,批量刪除(如引入的 UI 框架只用到 20% 樣式,可剔除 80% 冗余)。
示例:
關鍵 CSS 內嵌 + 異步加載非關鍵 CSS:
<head>
<style>
.header { height: 60px; }
.banner { width: 100%; }
</style>
<link rel="preload" href="non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
</head>
- 合并 + 壓縮 JS:將多個 JS 文件合并(如
util.js 、api.js 合并為app.js ),并用 Terser 等工具壓縮(混淆變量名、刪除空格注釋);
- 異步加載非核心 JS:對廣告、統計、聊天工具等非首屏必需的 JS,添加
async 或defer 屬性,避免阻塞 HTML 解析:
async :下載完成后立即執行(順序不確定);
defer :下載完成后等待 HTML 解析完畢再執行(按順序執行);
- 避免全局變量污染:用 IIFE(立即執行函數)或模塊(ES6 Module)封裝代碼,減少全局變量(全局變量會常駐內存,且可能引發沖突);
- 優化 DOM 操作:頻繁操作 DOM(如循環中修改元素)會導致多次回流,建議先在內存中構建 DOM 片段,再一次性插入頁面:
const list = document.getElementById('list');
for (let i = 0; i < 100; i++) {
list.innerHTML += `<li>Item ${i}</li>`;
}
優化后(內存中構建):
const list = document.getElementById('list');
let html = '';
for (let i = 0; i < 100; i++) {
html += `<li>Item ${i}</li>`;
}
list.innerHTML = html;
- 添加索引:對頻繁查詢的字段(如用戶 ID、訂單號、時間)添加索引(如 MySQL 的
ALTER TABLE orders ADD INDEX idx_user_id (user_id) ),查詢時間可從秒級降至毫秒級;
- 避免全表掃描:杜絕
SELECT * FROM table (尤其大表),只查詢需要的字段(如SELECT id, name FROM user );
- 優化 JOIN 操作:多表關聯查詢時,確保關聯字段有索引,且避免關聯超過 3 張表(可拆分查詢或用緩存);
- 分頁查詢:對大量數據(如列表頁)用
LIMIT 分頁(如SELECT * FROM articles LIMIT 10, 20 ),避免一次性加載全部數據。
SELECT * FROM users WHERE register_time > '2023-01-01';
優化后(添加索引 + 限制字段):
ALTER TABLE users ADD INDEX idx_register_time (register_time);
SELECT id, username FROM users WHERE register_time > '2023-01-01';
- 緩存高頻查詢結果:用 Redis 或 Memcached 緩存數據庫查詢結果(如熱門商品信息、首頁數據),設置合理過期時間(如 10 分鐘),避免頻繁訪問數據庫;
- 緩存靜態資源:對不常變化的頁面(如關于我們、幫助中心)生成靜態 HTML 文件,用戶訪問時直接返回靜態文件,無需后端動態渲染;
- 避免緩存穿透:對不存在的請求(如查詢 ID=-1 的數據),也緩存空結果(設置短過期時間,如 1 分鐘),防止惡意攻擊耗盡數據庫資源。
def get_product(id):
cache_key = f"product:{id}"
product = redis.get(cache_key)
if product:
return json.loads(product)
product = db.query("SELECT * FROM products WHERE id = %s", id)
if product:
redis.setex(cache_key, 600, json.dumps(product))
return product
- 減少循環嵌套:避免多層循環(如 3 層以上
for 循環),改用哈希表(字典)查詢(時間復雜度從 O (n²) 降至 O (n));
- 復用對象 / 變量:在循環中避免重復創建對象(如
for 循環內新建List 、Map ),應在循環外創建后復用;
- 異步處理非核心邏輯:對非實時需求(如日志記錄、數據統計),用消息隊列(如 RabbitMQ、Kafka)異步處理,避免阻塞主流程。
List<User> users = ...;
List<Order> orders = ...;
for (User u : users) {
for (Order o : orders) {
if (u.getId() == o.getUserId()) {
}
}
}
優化后(用哈希表優化查詢):
Map<Long, List<Order>> orderMap = new HashMap<>();
for (Order o : orders) {
orderMap.computeIfAbsent(o.getUserId(), k -> new ArrayList<>()).add(o);
}
for (User u : users) {
List<Order> userOrders = orderMap.getOrDefault(u.getId(), Collections.emptyList());
}
- 前端構建工具:用 Webpack、Vite 自動完成 JS/CSS 的合并、壓縮、Tree-Shaking(刪除未引用代碼);
- 代碼檢查工具:ESLint(JS)、StyleLint(CSS)檢測冗余代碼和低效寫法;
- 性能分析工具:Chrome DevTools(前端代碼執行時間)、Py-Spy(Python 后端)、Arthas(Java 后端)定位性能瓶頸;
- CDN + 邊緣計算:將靜態 JS/CSS 部署到 CDN,動態接口用邊緣計算節點加速(如 Cloudflare Workers),減少跨地域傳輸延遲。
- 緊急:壓縮 JS/CSS、刪除未使用代碼、數據庫加索引、異步加載非核心 JS;
- 重要:優化 DOM 操作、緩存高頻查詢、合并文件減少請求;
- 長期:重構低效算法、優化數據庫結構、引入性能監控工具。
通過以上方法,代碼相關的加載時間可減少 40%-60%,服務器響應速度提升 2-10 倍。 |