阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 减少HTTP请求数量的方法

减少HTTP请求数量的方法

作者:陈川 阅读数:14306人阅读 分类: 性能优化

HTTP请求数量是影响网页性能的关键因素之一。过多的请求会导致页面加载时间延长,用户体验下降。通过合并资源、使用雪碧图、内联关键CSS等技术手段,可以有效减少请求次数,提升页面性能。

合并CSS和JavaScript文件

将多个CSS或JavaScript文件合并为单个文件是最直接的优化方法。每个文件都需要单独的HTTP请求,合并后可以显著减少请求数量。

// 合并前
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="components.css">

// 合并后
<link rel="stylesheet" href="all.css">

构建工具如Webpack、Gulp等可以自动化完成这个过程:

// webpack.config.js
module.exports = {
  entry: {
    app: ['./src/js/main.js', './src/js/utils.js']
  },
  output: {
    filename: 'bundle.js'
  }
}

使用CSS雪碧图

雪碧图(Sprite)将多个小图标合并到一张大图中,通过CSS背景定位显示特定部分。这特别适合导航图标、社交按钮等场景。

.icon {
  background-image: url('sprite.png');
  background-repeat: no-repeat;
}

.icon-home {
  width: 32px;
  height: 32px;
  background-position: 0 0;
}

.icon-user {
  width: 32px;
  height: 32px;
  background-position: -32px 0;
}

现代构建工具可以自动生成雪碧图和对应的CSS:

// 使用gulp.spritesmith
const gulp = require('gulp');
const spritesmith = require('gulp.spritesmith');

gulp.task('sprite', function() {
  return gulp.src('images/icons/*.png')
    .pipe(spritesmith({
      imgName: 'sprite.png',
      cssName: 'sprite.css'
    }))
    .pipe(gulp.dest('dist'));
});

内联关键CSS

将首屏渲染所需的关键CSS直接内联到HTML中,可以避免额外的请求阻塞渲染。剩余的非关键CSS可以异步加载。

<head>
  <style>
    /* 关键CSS */
    body { font-family: sans-serif; }
    .header { background: #333; }
    .hero { padding: 2em; }
  </style>
  <!-- 异步加载剩余CSS -->
  <link rel="preload" href="non-critical.css" as="style" onload="this.rel='stylesheet'">
</head>

使用Base64编码内联小图片

对于小于2KB的图片,可以考虑转换为Base64编码直接嵌入CSS或HTML中,省去额外的HTTP请求。

.logo {
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AkEEjUXKw0bJQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAJklEQVQ4y2NgGAWjYBSMglEwCkbBKBgFowAAATMAZ/8Pq/kAAAAASUVORK5CYII=');
}

使用字体图标替代图片图标

字体图标将图标作为字符处理,一个字体文件可以包含数百个图标,只需一次HTTP请求。

<link rel="stylesheet" href="font-awesome.css">

<i class="fa fa-user"></i>
<i class="fa fa-home"></i>
<i class="fa fa-cog"></i>

延迟加载非关键资源

使用懒加载技术延迟加载首屏外的图片、iframe等资源,减少初始请求数量。

<img data-src="image.jpg" class="lazyload" alt="示例图片">

<script>
document.addEventListener("DOMContentLoaded", function() {
  const lazyImages = [].slice.call(document.querySelectorAll("img.lazyload"));
  
  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  }
});
</script>

使用HTTP/2服务器推送

HTTP/2的服务器推送功能允许服务器主动发送资源,减少往返请求。

# nginx配置示例
http2_push /style.css;
http2_push /main.js;

合理设置缓存策略

通过设置适当的缓存头,使浏览器可以重复使用已下载的资源,避免重复请求。

# nginx缓存配置
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
  expires 365d;
  add_header Cache-Control "public, no-transform";
}

使用WebP格式图片

WebP格式通常比PNG或JPEG更小,可以减少图片请求的传输时间。

<picture>
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="示例图片">
</picture>

减少第三方脚本的使用

评估第三方脚本的必要性,合并或移除不必要的跟踪代码、社交插件等。

<!-- 避免这样 -->
<script src="analytics.js"></script>
<script src="social-share.js"></script>
<script src="chat-widget.js"></script>

<!-- 改为按需加载 -->
<button id="load-chat">需要帮助?点击加载聊天窗口</button>
<script>
document.getElementById('load-chat').addEventListener('click', function() {
  const script = document.createElement('script');
  script.src = 'chat-widget.js';
  document.body.appendChild(script);
});
</script>

使用Service Worker缓存资源

Service Worker可以拦截网络请求,实现更精细的缓存控制。

// service-worker.js
const CACHE_NAME = 'v1';
const urlsToCache = [
  '/',
  '/styles/main.css',
  '/scripts/main.js',
  '/images/logo.png'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  );
});

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

优化API请求

合并API端点,使用GraphQL等查询语言减少数据请求次数。

// 传统REST API
fetch('/api/user/123');
fetch('/api/user/123/posts');

// GraphQL查询
fetch('/graphql', {
  method: 'POST',
  body: JSON.stringify({
    query: `
      {
        user(id: 123) {
          name
          email
          posts {
            title
            date
          }
        }
      }
    `
  })
});

使用CDN加速资源加载

内容分发网络(CDN)可以减少资源请求的物理距离,提高加载速度。

<!-- 使用CDN加载常用库 -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">

预加载关键资源

使用<link rel="preload">提前加载关键资源,避免请求阻塞。

<head>
  <link rel="preload" href="critical.css" as="style">
  <link rel="preload" href="main.js" as="script">
  <link rel="preload" href="hero-image.jpg" as="image">
</head>

减少重定向

避免不必要的重定向,每个重定向都会产生额外的HTTP请求。

# 避免这样
location /old-page {
  return 301 /new-page;
}

# 直接链接到最终地址
<a href="/new-page">转到新页面</a>

使用SVG替代部分图片

SVG是矢量格式,通常文件更小,可以内联到HTML中。

<!-- 内联SVG示例 -->
<svg width="100" height="100" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#f00"/>
</svg>

优化网页字体使用

合理使用字体,避免过多字体变体导致额外请求。

/* 避免这样 */
@font-face {
  font-family: 'MyFont';
  src: url('myfont-regular.woff2') format('woff2');
  font-weight: 400;
}
@font-face {
  font-family: 'MyFont';
  src: url('myfont-bold.woff2') format('woff2');
  font-weight: 700;
}

/* 使用unicode-range分割字体文件 */
@font-face {
  font-family: 'MyFont';
  src: url('myfont-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF;
}

减少Cookie大小

过大的Cookie会在每个请求中自动发送,增加请求负载。

// 设置Cookie时指定路径,避免全局Cookie
document.cookie = "preferences=dark; path=/settings; max-age=31536000";

使用模块化JavaScript

现代JavaScript模块系统可以更好地控制代码分割和按需加载。

// 动态导入模块
button.addEventListener('click', async () => {
  const module = await import('./module.js');
  module.doSomething();
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌