网站速度优化

134 阅读7分钟

性能优化和SEO优化之间存在着密切的关系。虽然两者关注的重点不同,但它们相互影响,共同作用于网站的整体表现。以下是性能优化如何直接影响SEO优化的具体方式。网站速度优化是性能优化关注点之一。

压缩和优化图像

  • 压缩图像:使用工具如 TinyPNG、ImageOptim 或 Squoosh 进行无损压缩。
  • 选择合适格式:JPEG 适用于照片,WebP 提供更好的压缩比,SVG 适用于矢量图形。

缩小 CSS 和 JavaScript 文件

  • 使用工具如 UglifyJS 或 Terser 压缩 JavaScript 文件,使用 Clean-CSS 压缩 CSS 文件。
  • 将多个 CSS 和 JS 文件合并成一个文件,减少 HTTP 请求的数量。

启用缓存、使用CDN服务等措施加快页面加载速度。

JavaScript
const express = require('express');
const path = require('path');
const fs = require('fs');
const http = require('http');

const app = express();

// 设置静态文件目录
// 静态文件目录为 `public`,并且使用 `setHeaders` 回调函数来设置每个文件的HTTP头。
// 在服务器配置中设置适当的缓存头,以便浏览器可以缓存静态资源。
app.use(express.static(path.join(__dirname, 'public'), {
  setHeaders: (res, filePath) => {
    const ext = path.extname(filePath);
    const contentType = mime.getType(ext);

    // 设置Expires头
    // Expires Header:设置未来的日期,指示浏览器何时再次检查资源是否已更新。资源将在一年后的某个时间过期
    const oneYearLater = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000);
    res.setHeader('Expires', oneYearLater.toUTCString());

    // 设置Cache-Control头
    // 使用 Cache-Control 指令来控制缓存行为。
    // 根据不同类型的资源设置不同的 `Cache-Control` 头。例如,图片和JavaScript文件设置为一年内不检查更新,CSS文件设置为一个月内不检查更新。
    if (contentType.startsWith('image/') || contentType === 'application/javascript') {
      res.setHeader('Cache-Control', 'public, max-age=31536000'); // 一年
    } else if (contentType === 'text/css') {
      res.setHeader('Cache-Control', 'public, max-age=2592000'); // 一个月
    }
  }
}));

// 启动服务器
const PORT = process.env.PORT || 3000;
const server = http.createServer(app);
server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

启用缓存是提高应用程序性能的重要手段之一。无论是前端还是后端开发,都可以通过多种方式启用缓存来减少对昂贵资源(如数据库查询、API 请求等)的访问频率。下面是几个常见的方式来进行缓存优化:

后端缓存

使用 Redis 缓存

Redis 是一种高性能的键值存储系统,非常适合用于高速缓存数据。

安装 Redis 客户端

首先安装 Redis 客户端库:

Shell
npm install redis
示例代码:从 Redis 获取数据
JavaScript
const redis = require('redis');
const client = redis.createClient({
  host: 'localhost',
  port: 6379,
});

client.on('error', (err) => console.error(err));

async function getDataFromCache(key) {
  return new Promise((resolve, reject) => {
    client.get(key, (err, res) => {
      if (err) reject(err);
      resolve(res);
    });
  });
}

async function setDataToCache(key, value, ttlInSeconds) {
  return new Promise((resolve, reject) => {
    client.setex(key, ttlInSeconds, value, (err, res) => {
      if (err) reject(err);
      resolve(res);
    });
  });
}

(async () => {
  try {
    let cachedData = await getDataFromCache('myKey');

    if (!cachedData) {
      // 模拟从数据库获取数据
      const dbData = 'Some database data';
      await setDataToCache('myKey', dbData, 60); // 设置缓存有效期为60秒
      cachedData = dbData;
    }

    console.log(cachedData);
  } catch (err) {
    console.error(err);
  }
})();

前端缓存

浏览器本地存储

使用 localStorage 或 sessionStorage 存储数据。

示例代码:使用 localStorage 缓存数据
JavaScript
function getFromLocalStorage(key) {
  return JSON.parse(localStorage.getItem(key));
}

function saveToLocalStorage(key, data) {
  localStorage.setItem(key, JSON.stringify(data));
}

function fetchData() {
  const cachedData = getFromLocalStorage('myKey');

  if (cachedData !== null && cachedData.timestamp > Date.now() - (1 * 60 * 1000)) { // 缓存有效时间为1分钟
    console.log('Using cached data:', cachedData.data);
    return cachedData.data;
  } else {
    // 模拟从API获取数据
    fetch('/api/data')
      .then(response => response.json())
      .then(data => {
        saveToLocalStorage('myKey', { timestamp: Date.now(), data });
        console.log('Fetched fresh data:', data);
      })
      .catch(error => console.error(error));
  }
}

fetchData();

Web 应用缓存

Service Worker 缓存

Service Worker 可以拦截网络请求并在本地缓存资源。

示例代码:注册 Service Worker 并设置缓存策略
JavaScript
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js').then(registration => {
      console.log('Service worker registered with scope:', registration.scope);
    });
  });
}
Service Worker 文件 (sw.js)
JavaScript
self.addEventListener('install', event => {
  self.skipWaiting(); // 立即激活 service worker
});

self.addEventListener('activate', event => {
  event.waitUntil(self.clients.claim()); // 控制所有客户端
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

总结

启用缓存可以通过多种方式进行,具体取决于应用场景和需求。对于后端服务,可以考虑使用 Redis 或其他内存缓存解决方案;对于前端应用,则可以利用浏览器提供的本地存储功能或 Service Worker 技术。通过合理的缓存策略,可以显著提升应用程序的整体性能和用户体验。

使用 CDN(内容分发网络)

  • CDN 分布式存储:使用 CDN 如 Cloudflare、Akamai 或 Amazon CloudFront 来加速全球范围内的内容交付。
  • 边缘缓存:CDN 在地理位置较近的节点缓存内容,减少延迟。
    CDN(Content Delivery Network,内容分发网络)是一种分布式网络架构,旨在通过在全球范围内分布的内容服务器来加速网页和其他数字内容的传递。

CDN的基本概念

分布式服务器网络

CDN由一组分布在世界各地的服务器组成。这些服务器被称为“边缘服务器”,因为它们位于互联网的“边缘”,更接近最终用户的位置。

内容缓存

当用户请求某个网站的内容时,CDN会将该内容从最近的边缘服务器提供给用户,而不是直接从原始服务器(通常称为源站)。这样可以减少数据传输的距离,从而降低延迟。

CDN如何加快页面加载速度

减少网络延迟

由于边缘服务器靠近用户,因此减少了数据传输的时间。例如,在中国的一个用户访问美国托管的网站时,如果通过CDN,可能会从中国的某个边缘服务器获取内容,而不需要跨越整个太平洋。

加速静态资源加载

大多数网站包含大量的静态资源(如CSS、JavaScript文件和图像)。这些资源可以在多个用户的请求之间被缓存下来,并快速提供给后续请求者。这不仅提高了响应速度,还减轻了源站服务器的压力。

平衡负载

通过分散流量到多个边缘服务器上,CDN有助于平衡负载。即使某些区域的需求激增,也不会影响整体性能。

提高可用性和可靠性

如果某个特定地区的边缘服务器出现故障或维护,其他地区的服务仍然可以正常运行。此外,CDN还能自动检测并绕过故障点,确保持续的服务质量。

具体实现案例

假设有一个网站 example.com 使用了Cloudflare作为其CDN提供商:

  1. 用户访问 https://example.com/index.html

  2. DNS解析指向Cloudflare的一个边缘节点。

  3. 边缘节点检查是否有缓存版本的HTML文档。

    • 如果有,则立即返回给用户;
    • 如果没有,则从源站拉取最新版本并缓存起来再返回给用户。
  4. 用户继续请求页面中的其他静态资产(比如CSS或JavaScript文件)。

  5. 边缘服务器根据之前提到的原则处理这些请求,并尽可能快地提供所需的内容。

结论

总之,通过使用CDN,网站能够显著改善其性能指标——尤其是对于那些拥有国际受众或者需要快速响应时间的应用来说尤为重要。它不仅能缩短用户等待时间,还能增强用户体验并提高业务效率。

压缩传输内容

  • 启用 Gzip 压缩:在服务器端启用 Gzip 压缩,减小传输的数据量。
  • Brotli 压缩:现代浏览器支持 Brotli 压缩,进一步减小文件大小。

异步加载脚本

  • 异步加载:使用 async 或 defer 属性异步加载 JavaScript 文件,防止阻塞页面渲染。
  • Lazy Loading:使用懒加载技术延迟加载非关键资源,如图片和脚本。
<!-- 异步加载脚本 --> 
<script src="scripts/main.js" async></script> 
<!-- 懒加载图片 --> 
<img src="placeholder.jpg" data-src="actual-image.jpg" loading="lazy" alt="Description">

最小化 HTTP 请求

  • 合并文件:将多个 CSS 和 JS 文件合并成一个文件。
  • 内联关键 CSS:将关键 CSS 内联到 HTML 中,减少初始加载时间。

使用 Web 字体优化

  • 限制字体数量:只使用必要的字体,避免过多的 HTTP 请求。
  • 预加载字体:使用 加速字体加载。

优化数据库查询

  • 索引优化:为经常查询的列创建索引,提高查询性能。确保数据库查询高效,减少页面加载时间。
  • 缓存查询结果:使用缓存机制减少数据库请求次数,使用缓存层如 Redis 或 Memcached 缓存频繁查询的结果。
SQL
-- 创建索引
CREATE INDEX idx_user_name ON users(name);

-- 使用缓存查询结果
SELECT * FROM posts WHERE user_id = ? CACHE 1 HOUR;

使用性能监控工具

  • PageSpeed Insights:Google 提供的工具,评估网站性能并提供建议。
  • GTmetrix:提供详细的性能报告和优化建议。
  • Lighthouse:Chrome 开发者工具中的内置工具,提供全面的性能评估。