邱敬幃 Pardn Chiu
目錄瀏覽器快取利用何時使用快取:何時重新請求資源:圖片的優化與設定懶加載(Lazy Loading)壓縮圖片:設定懶加載(Lazy Loading):CSS 和 JavaScript 的優化優化CSS:合併CSS文件:壓縮 CSS:優化 JavaScript:合併和壓縮 JavaScript 文件:使用異步載入:優化 DOM 操作:使用事件代理(Event Delegation):壓縮技術配置 Gzip 壓縮:配置 Brotli 壓縮:重新啟動 Nginx 服務:附載平衡(Load balancing)異步處理連接池的使用內容傳遞網絡(CDN)的重要性CDN的工作原理:測試和性能監控工具Chrome DevTools:Google PageSpeed Insights:Lighthouse:WebPageTest:相關連結
標籤

網站極速提升!網頁加速優化必備策略大揭秘

透過優化技巧讓你的網站達到極致的載入速度

226次觀看 0收藏 前端開發
提供更快的網頁加載速度不只能提高用戶體驗,更是今日網站 SEO 優化的關鍵重點之一。
本文深入探討了各種網頁加速技巧幫助您加快網頁載入速度,提高性能,包括利用快取技術減少請求等待時間、使用圖片優化技巧來縮小圖片文件大小、懶加載加速畫面載入、壓縮數據以節省帶寬、實現附載平衡以提高伺服器效能、使用異步處理來減少阻塞,以及有效管理數據庫連接池以提高查詢效率。

瀏覽器快取利用

瀏覽器快取是一個用於存儲網頁資源的臨時性存儲區域,旨在提高網站性能和減少用戶等待時間。當您訪問一個網站時,瀏覽器會下載網頁的各種資源,例如 HTML、CSS、JavaScript、圖片等。這些資源通常包括在 HTTP 請求中,從伺服器獲取。

如何利用瀏覽器快取來提高網站性能。當您訪問一個網站時,瀏覽器可以將某些資源存儲在本地,這樣下次訪問相同頁面時就不需要再次下載這些資源了。

何時使用快取:

瀏覽器會根據 HTTP 標頭中的快取控制訊息來判斷何時使用快取。這些標頭包括:

  • Cache-Control:
    指定資源的快取策略,例如public(可以被公開快取)或private(僅可以被私有快取)。
  • Expires:
    指定資源的過期時間,之後瀏覽器將不再使用快取的版本。
  • Last-Modified:
    指定資源的最後修改時間,可用於檢查資源是否已經變更。

何時重新請求資源:

當瀏覽器需要一個資源,它會檢查快取中是否已經存在該資源的副本。如果存在並且未過期,瀏覽器將直接使用快取的版本,而不重新請求伺服器。只有在以下情況下,瀏覽器將重新請求資源:

  • 首次訪問。
  • 快取中已經過期。
  • 使用者強制刷新頁面(Ctrl + F5 或 Cmd + Shift + R)。
  • 快取被伺服器指示不使用(Cache-Control: no-cache)。

瀏覽器快取是一個優化工具,它通過存儲和重複使用網站資源,提高了網站載入速度,但需要仔細配置以確保資源的有效性和更新。

快取就像是我們放在工作桌旁的點心箱(瀏覽器快取),在我們想吃的時候可以直接使用(讀取快取),而不必再起身去超商補貨。

圖片的優化與設定懶加載(Lazy Loading)

圖片是網站中常見的大型資源,我們可以通過壓縮和使用現代格式來減小它們的大小,提高頁面載入速度。

壓縮圖片:

壓縮圖片是減小圖片文件大小的關鍵。您可以使用多種工具來執行此操作,例如:

  • Adobe Photoshop:
    打開圖片,選擇「優化」選項,然後調整壓縮質量。
  • TinyPNG 和 TinyJPG:
    在線工具,可自動壓縮圖片,並保持高質量。

設定懶加載(Lazy Loading):

Can I Use: 大多數現代瀏覽器已經支持它,可以放心在網頁中使用來提高性能。

使用 HTML 的 loading 屬性: 懶加載可以使網頁僅在用戶捲動到圖片時才載入圖片。這可通過 HTML 的 loading 屬性來實現。例如:

  1. <img src="placeholder.jpg" data-src="image.jpg" loading="lazy" alt="描述">

使用 data-src 屬性輸入的 URL,loading="lazy" 表示使用懶加載。

使用 JavaScript 函數: 如果需要更多控制,您可以使用 JavaScript 函數來實現懶加載。以下是一個簡單的範例,使用 JavaScript 檢測圖片是否出現在視窗中,如果是,則將 src 屬性中的圖片 URL 設置為 data-src 的值:

  1. const ary = document.querySelectorAll("img[lazyload='lazy']");
  2. const observer = new IntersectionObserver((entries, observer) => {
  3.     entries.forEach((entry) => {
  4.         if (entry.isIntersecting) {
  5.             const img = entry.target;
  6.             img.src = img.dataset.src;
  7.             observer.unobserve(img);
  8.         };
  9.     });
  10. }, {
  11.     root: null,
  12.     rootMargin: "0px",
  13.     threshold: 0.5, // 當圖片的 50% 出現在視口中時載入
  14. });
  15. ary.forEach((img) => {
  16.     observer.observe(img);
  17. });
懶加載就像是我們在吃到飽餐廳中,需要吃什麼(進入畫面中)才點什麼(載入數據)。

CSS 和 JavaScript 的優化

最小化和合併 CSS 和 JavaScript 可以減少HTTP請求並改進性能。

優化CSS:

優化 CSS 是提高網頁性能的關鍵之一。以下是一些優化 CSS 的方法和具體代碼範例:

合併CSS文件:

減少HTTP請求次數是一個重要的目標,所以您可以將多個CSS文件合併成一個,以減少請求數。

  1. <link rel="stylesheet" href="styles.css">
壓縮 CSS:

利用工具壓縮 CSS 文件,例如CSSNanoUglifyCSS,去除不必要的空格、註釋和無用代碼。

  1. /* 未壓縮 */
  2. body {
  3.   background-color: #ffffff;
  4.   font-family: Arial, sans-serif;
  5. }
  6. /* 壓縮 */
  7. body{background-color:#fff;font-family:Arial,sans-serif;}

優化 JavaScript:

JavaScript 優化可以提高網頁性能和反應速度。以下是一些優化 JavaScript 的方法和具體代碼範例:

合併和壓縮 JavaScript 文件:

合併多個 JavaScript 文件並壓縮它們,以減少請求次數和文件大小。

  1. <script src="index.js"></script>
使用異步載入:

使用 asyncdefer 屬性,將不必要的 JavaScript 代碼推遲載入,以改善頁面載入性能。

  1. <!-- 異步 -->
  2. <script src="script.js" async></script>
  3. <!-- 推遲 -->
  4. <script src="script.js" defer></script>
優化 DOM 操作:

優化 DOM 操作是提高網頁性能的重要一環。DOM 操作觸發了瀏覽器的回流(reflow)和重繪(repaint),這些操作需要大量的計算資源。以下是一些優化 DOM 操作的技巧:

  • 批處理 DOM 操作:
    盡可能將多個 DOM 操作合併為單個批處理操作。例如,如果需要添加多個元素到 DOM 中,可以先創建它們,然後一次性將它們附加到 DOM。這減少了回流和重繪的次數。
  • 使用 DocumentFragment:
    使用 DocumentFragment 可以在不直接影響 DOM 的情況下進行多個操作。您可以將要添加到 DOM 中的元素先添加到 DocumentFragment,然後將整個 DocumentFragment 附加到 DOM。這樣可以減少回流次數。
  1. const fragment = document.createDocumentFragment();
  2. const elm1 = document.createElement('div');
  3. elm1.innerText = '元素1';
  4. fragment.appendChild(elm1);
  5. const elm2 = document.createElement('div');
  6. elm2.innerText = '元素2';
  7. fragment.appendChild(elm2);
  8. [TARGET].appendChild(fragment);
  • 避免不必要的 DOM 操作:
    謹慎執行 DOM 操作。在修改 DOM 之前,請仔細考慮是否有更好的方法來達到相同的目標。避免不必要的元素創建、屬性設置或樣式更改。
  • 使用事件委派(Event Delegation):
    減少事件監聽器的數量。將事件監聽器附加到父元素,然後在事件冒泡時捕獲事件並確定目標元素。這樣可以減少監聽器的數量,提高效率。
  • 分離讀取和寫入操作:
    分離 DOM 操作。首先進行讀取操作,然後再進行寫入操作。這可以減少回流的次數,因為瀏覽器可以優化讀取操作。在讀取階段,您可以獲取 DOM 元素的信息,但不修改它們的內容、樣式或佈局。這有助於避免回流。
  1. const elm = document.getElementById('target');
  2. const elmW = element.clientWidth;
  3. const elmH = element.clientHeight;
  4. // 資料都讀取完後,在進行寫入動作
  5. elm.style.width = elmW + 100 + "px";
  6. elm.style.height = elmH <= 80 ? '5rem' : elmH;
  • 使用 requestAnimationFrame:
    如果需要在下一個繪製幀之前執行 DOM 操作,使用 requestAnimationFrame 來執行它們。這將確保 DOM 操作在繪製之前進行,從而減少回流和重繪的次數。
  1. // 封裝 DOM
  2. function updateDOM() {
  3.     const elm = document.getElementById('target');
  4.     elm.style.width = '10rem';
  5.     elm.style.height = '5rem';
  6. };
  7. // 使用 requestAnimationFrame 調用函數:
  8. requestAnimationFrame(updateDOM);
  • 使用虛擬列表或無限滾動:
    如果您有大量數據要顯示,考慮使用虛擬列表或無限滾動技術,以僅渲染可見區域內的內容,而不是整個列表。這可以減少 DOM 元素的數量。
  • 減少重排和重繪:
    修改元素的樣式時,避免頻繁的更改。優先使用 CSS 的 class 切換,而不是直接設置樣式屬性。這可以幫助減少回流和重繪。
  1. div {
  2.     width: 20rem;
  3.     height: 10rem;
  4. }
  5. div.new {
  6.     width: 10rem;
  7.     height: 5rem;
  8. }
  1. const elm = document.getElementById('target');
  2. elm.classList.add('new');
使用事件代理(Event Delegation):

將事件監聽器添加到父元素,以減少事件處理程序的數量。


壓縮技術

現在,讓我們深入研究壓縮技術,如 Gzip 和 Brotli。它們可以幫助我們節省帶寬並提高載入速度。打開 Nginx 的配置文件,通常位於 /etc/nginx/nginx.conf/etc/nginx/sites-available/default。在 http 區塊中,添加以下配置:

配置 Gzip 壓縮:

以下是如何在 Nginx 伺服器上配置 Gzip 壓縮的範例:

  1. http {
  2.     gzip on;
  3.     gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
  4.     gzip_min_length 1000;
  5.     gzip_proxied any;
  6.     gzip_vary on;
  7.     gzip_disable "MSIE [1-6]\.";
  8. }

配置 Brotli 壓縮:

以下是如何在 Nginx 伺服器上配置 Brotli 壓縮的範例:

  1. http {
  2.     brotli on;
  3.     brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
  4.     brotli_comp_level 6;
  5.     brotli_buffers 16 8k;
  6.     brotli_min_length 1000;
  7. }

重新啟動 Nginx 服務:

  1. sudo service nginx restart
壓縮就像是我們將客戶網路所購買的東西,盡可能的塞入最小的紙箱(最小化數據)中後寄出,以節省運輸費用(流量)。

附載平衡(Load balancing)

附載平衡是一種分散網路流量的技術,它將傳入的請求分發到多個伺服器,以確保高可用性、性能優化和數據處理能力擴展。這有助於避免單點故障,提供更好的用戶體驗,以及有效地處理大量的請求。以下是一個使用 Nginx 實現附載平衡的範例:

  1. http {
  2.     # 請確保將伺服器的 IP 位置和 port 替換為您自己的伺服器設置。
  3.     upstream servers {
  4.         server 10.10.10.101:80;  # 伺服器1: 80 port
  5.         server 10.10.10.102:80;  # 伺服器2: 80 port
  6.         server 10.10.10.103:80;  # 伺服器3: 80 port
  7.     }
  8.     server {
  9.         listen 80;
  10.         server_name yourdomain.com;
  11.         location / {
  12.             proxy_pass http://servers;
  13.             proxy_set_header Host $host;
  14.             proxy_set_header X-Real-IP $remote_addr;
  15.         }
  16.     }
  17. }

它將傳入的請求分發到三個後端伺服器,以平衡流量和提高可用性。這樣,您的網站可以更好地應對高流量和故障情況,提供更好的用戶體驗。

附載平衡就像是直接提供多台販賣機,來確保儘管一群人使用時,排隊(等候)時間也會縮短。

異步處理

異步處理是一種用於處理可能需要等待時間的任務。當執行異步任務時,代碼將繼續運行,而不必等待任務完成。這有助於避免阻塞應用程序,提高用戶體驗。

以下是一個使用 Node.js 中的 async 套件來處理異步任務的範例。async 套件提供了多個實用的函數,用於處理異步操作,特別是當您需要按特定順序執行它們時。

  1. const async = require('async'); // 需要安裝 async 套件
  2. // 同時處理 task1、task2 的任務
  3. async.auto({
  4.     task1: (next) => {
  5.         // 模擬讀取資料,1 秒後完成
  6.         setTimeout(() => {
  7.             next(null, '任務1 完成');
  8.         }, 1000);
  9.     },
  10.     task2: (next) => {
  11.         // 模擬讀取資料,2 秒後完成
  12.         setTimeout(() => {
  13.             next(null, '任務2 完成');
  14.         }, 2000);
  15.     }
  16. }, (err, results) => {
  17.     // task1、task2 皆完成,則進行以下動作
  18.     if (err) return  console.error('Error:', err); 
  19.     console.log('任務皆完成');
  20. });
異步處理就像是我們在煮泡麵時,不需要等水滾了再打開泡麵,而是在加熱水的過程當中,我們就可以先把調味包加到碗裡。

連接池的使用

連接到數據庫的過程通常是一個耗時的操作,並且在每次查詢後關閉連接可能會浪費資源。而連接池有助於提高應用程序的效能,減少資源浪費。以下是一個簡單的連接池使用示例,以數據庫連接為例:

  1. const mysql = require('mysql');  // 需要安裝 mysql 套件
  2. const db = mysql.createPool({
  3.     connectionLimit: 10,
  4.     host: 'localhost',
  5.     user: 'your_username',
  6.     password: 'your_password',
  7.     database: 'your_database',
  8. });
  9. function query(queryText) {
  10.     return new Promise((resolve, reject) => {
  11.         db.getConnection((err, connection) => {
  12.             if (err) return reject(err);
  13.             connection.query(queryText, (queryErr, results) => {
  14.                 connection.release();
  15.                 if (queryErr) return reject(queryError);
  16.                 resolve(results);
  17.             });
  18.         });
  19.     });
  20. };
  21. // 使用連接池查詢數據
  22. query('SELECT * FROM your_table')
  23.     .then((results) => {
  24.         console.log('Success:', results);
  25.     })
  26.     .catch((error) => {
  27.         console.error('Error:', error);
  28.     });

內容傳遞網絡(CDN)的重要性

CDN 是「內容傳遞網絡」(Content Delivery Network)的縮寫。它是一個分佈式網絡基礎架構,用於提供高效、快速和可靠的內容傳遞服務。CDN 的目標是優化內容傳遞,減少網絡擁塞,降低載入時間,提高用戶體驗。

CDN的工作原理:

  • 伺服器分佈:
    CDN 提供商(例如: CloudflareGoogle Cloud CDN)在全球各地建立了多個數據中心,這些數據中心稱為「邊緣伺服器」。這些伺服器位於距離用戶最近的地理位置。
  • 內容複製:
    靜態資源(如圖片、CSS 和 JavaScript 文件)被複製到 CDN 的邊緣伺服器中。當用戶訪問網站時,這些靜態資源會從最接近用戶的邊緣伺服器提供。
  • DNS 解析:
    當用戶在網絡瀏覽器中輸入網址,瀏覽器會對網址進行 DNS 解析,找到最接近用戶的 CDN 邊緣伺服器的 IP 地址。
  • 內容提供:
    用戶的請求會被導向到最近的 CDN 邊緣伺服器,該伺服器將相應的靜態資源提供給用戶。因為這些伺服器位於用戶附近,所以資源載入速度快。
  • 緩存管理:
    CDN 邊緣伺服器會將提供的內容暫存在本地,以減少對源伺服器的負載。這些緩存的內容在設定的時間後過期,以確保用戶獲得最新版本的資源。
  • 負載平衡:
    CDN 通常具有負載平衡機制,它們可以自動將流量分發到多個伺服器,以確保高可用性和性能。如果某個伺服器不可用,流量會自動路由到其他伺服器。
  • 內容更新:
    當網站的內容發生更改時,CDN 提供商會更新其邊緣伺服器中的複本,以確保用戶獲得最新版本的資源。

測試和性能監控工具

當您使用這些工具來優化網站時,測試和性能監控是關鍵的一部分。以下是一些實際的測試工具,以及如何使用它們來評估您的網站性能:

Chrome DevTools:

Chrome 瀏覽器的內置工具,提供實時性能分析,包括記憶體使用情況、CPU 使用情況和事件時間軸。這有助於識別網站中的性能問題並進行改進。

測試結果通常包括指標,如首次內容渲染時間、加載時間、資源大小和數量,以及建議的改進措施。通過定期使用這些工具進行性能測試,您可以追蹤網站的性能變化,識別瓶頸,並採取必要的措施來優化您的網站,提供更好的用戶體驗。

Google PageSpeed Insights:

為您的網站提供性能評分,並列出改進建議。該工具還會顯示用戶體驗數據,例如首次內容渲染時間和可交互時間。

Lighthouse:

Chrome 瀏覽器的內置工具,提供關於網站性能、可訪問性、最佳實踐和 SEO 的詳細報告。您可以查看各個項目的得分和建議,以改進網站。

WebPageTest:

提供詳細的性能報告,包括首次內容渲染時間、加載時間、資源分佈圖和水平線圖。您可以查看不同地點和設備的測試結果。


相關連結