顾乔芝士网

持续更新的前后端开发技术栈

rust 浏览器的压缩打包方式gzip Brotli Deflate Zstd比较

浏览器的 “压缩套餐”:原来它认识这么多 “打包方式”

先给压缩方法整个 “全家福”:浏览器是个挑剔的 “快递收件员”

想象你网购了一堆东西,快递员(浏览器)来收件时,只接受特定的打包方式(压缩方法)—— 有的认普通快递袋,有的认真空压缩袋,太新潮的可能还不认识。网页压缩也是一个道理:服务器把网页 “打包”(压缩),浏览器得认识这种 “打包方式” 才能正确 “拆包”(解压)。



目前浏览器主流支持的 “打包方式” 有 4 种,就像快递站的 4 种打包工具:



压缩方法

类比

特点

浏览器支持度

gzip

普通快递袋

发明早、应用广,速度快但压缩率一般

几乎所有浏览器(包括古董级 IE6)

Brotli

真空压缩袋 Pro

谷歌出品,压缩率高(比 gzip 小 10%-20%),稍慢

现代浏览器(Chrome 50+、Firefox 44 + 等)

Deflate

简易打包绳

比 gzip 稍简单,压缩率接近但应用少

大部分浏览器支持,但部分老浏览器有兼容问题

Zstd

智能打包机

Facebook 出品,速度和压缩率平衡,较新

较新浏览器(Chrome 113+、Firefox 112+)



今天咱们就挨个扒一扒这些 “打包方式”,再写个工具让你的浏览器 “自报家门”—— 看看它认识哪几种。

案例 1:让浏览器 “坦白”:我支持哪些压缩方法?

浏览器在请求网页时,会在Accept-Encoding请求头里 “告诉” 服务器:“我认识这些打包方式,你随便用!” 咱们写个简单网页,用 JavaScript 读取这个请求头,让浏览器自己说出来。

步骤 1:创建检测页面(compression_check.html)

html

预览

<!DOCTYPE html>
<html>
<head>
    <title>浏览器压缩支持检测</title>
    <style>
        body { font-family: Arial; max-width: 800px; margin: 20px auto; padding: 0 20px; }
        .support-box { border: 2px solid #eee; padding: 15px; margin: 10px 0; border-radius: 8px; }
        .supported { background: #f0fff4; border-color: #4cd964; }
        .not-supported { background: #fff0f0; border-color: #ff9500; }
        .title { font-weight: bold; font-size: 1.2em; margin-bottom: 10px; }
    </style>
</head>
<body>
    <h1>你的浏览器支持这些压缩方法吗?</h1>
    <p>(浏览器会在请求头里偷偷告诉服务器它认识的压缩方式,下面是检测结果)</p>

    <div id="result"></div>

    <script>
        // 注意:JavaScript在浏览器里不能直接读取请求头(出于安全限制)
        // 所以咱们用一个小技巧:通过访问一个服务器端点获取请求头
        // 这里为了简单,先模拟常见浏览器的情况,实际使用时需要后端配合
        function detectCompressionSupport() {
            // 模拟不同浏览器的Accept-Encoding(实际应从服务器获取)
            // 真实场景中,后端可以读取请求头并返回给前端
            const simulatedAcceptEncoding = "gzip, deflate, br, zstd"; // 现代Chrome的典型值
            
            // 要检测的压缩方法
            const compressions = [
                { name: "gzip", desc: "最常用的压缩方式,兼容性之王" },
                { name: "Brotli (br)", desc: "压缩率高,现代浏览器支持" },
                { name: "Deflate", desc: "较老的压缩方式,应用较少" },
                { name: "Zstd", desc: "较新的平衡型压缩方式" }
            ];

            const resultDiv = document.getElementById("result");
            
            compressions.forEach(comp => {
                // 检查是否支持(忽略大小写)
                const isSupported = simulatedAcceptEncoding.toLowerCase().includes(
                    comp.name.includes('(') ? comp.name.split('(')[1].replace(')', '') : comp.name
                );
                
                const box = document.createElement('div');
                box.className = `support-box ${isSupported ? 'supported' : 'not-supported'}`;
                box.innerHTML = `
                    <div class="title">${comp.name}:${isSupported ? ' 支持' : ' 不支持'}</div>
                    <div>${comp.desc}</div>
                `;
                resultDiv.appendChild(box);
            });

            // 显示原始请求头(模拟)
            const headerDiv = document.createElement('div');
            headerDiv.style.marginTop = "20px";
            headerDiv.innerHTML = `<strong>模拟的Accept-Encoding请求头:</strong>${simulatedAcceptEncoding}`;
            resultDiv.appendChild(headerDiv);
        }

        // 页面加载后检测
        window.onload = detectCompressionSupport;
    </script>
</body>
</html>

步骤 2:运行方法(超简单!)

  1. 把上面代码复制到文本编辑器,保存为compression_check.html(注意后缀是.html)。
  2. 双击这个文件,用你的浏览器打开(Chrome、Firefox、Edge 都行)。

预期效果:

页面会显示 4 种压缩方法的支持情况(基于模拟的现代浏览器数据),通常会看到:



  • gzip: 支持
  • Brotli (br): 支持
  • Deflate: 支持
  • Zstd: 支持(如果用的是较新浏览器)



如果用很老的浏览器(比如 IE8)打开,可能会看到 Brotli 和 Zstd 显示 “不支持”—— 这就是浏览器的 “代沟”~

案例 2:后端实战:根据浏览器支持动态选择压缩方法

光检测还不够,服务器得 “看菜下饭”—— 浏览器支持什么压缩,就用什么方法。咱们用 Rust 的hyper框架搭个服务器,实现这个逻辑。

步骤 1:创建 Rust 项目

bash

cargo new browser_compression_demo
cd browser_compression_demo

步骤 2:添加依赖(Cargo.toml)

toml

[dependencies]
hyper = { version = "1.1", features = ["full"] }  # HTTP服务器
tokio = { version = "1.0", features = ["full"] }  # 异步运行时
flate2 = "1.0"  # gzip和Deflate压缩
brotli = "3.3"  # Brotli压缩
zstd = "0.13"   # Zstd压缩

步骤 3:服务器代码(src/main.rs)

rust

use brotli::enc::BrotliEncoderParams;
use brotli::BrotliCompress;
use flate2::write::{DeflateEncoder, GzEncoder};
use flate2::Compression;
use hyper::{
    header::{ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_TYPE},
    service::{make_service_fn, service_fn},
    Body, Request, Response, Server,
};
use std::convert::Infallible;
use std::io::Write;
use std::net::SocketAddr;
use zstd::bulk::Compressor;

// 压缩内容:根据浏览器支持的方法选择最优解
fn compress_best(content: &str, accept_encoding: &str) -> (Vec<u8>, &'static str) {
    // 优先级:Brotli > Zstd > gzip > Deflate > 不压缩
    if accept_encoding.contains("br") {
        // Brotli压缩
        let mut params = BrotliEncoderParams::default();
        params.quality = 6;
        let mut compressed = Vec::new();
        let mut encoder = BrotliCompress::from_params(content.as_bytes(), &mut compressed, Pms);
        encoder.finish().unwrap();
        (compressed, "br")
    } else if accept_encoding.contains("zstd") {
        // Zstd压缩
        let mut compressor = Compressor::new(3).unwrap();
        let compressed = compressor.compress(content.as_bytes()).unwrap();
        (compressed, "zstd")
    } else if accept_encoding.contains("gzip") {
        // gzip压缩
        let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
        encoder.write_all(content.as_bytes()).unwrap();
        let compressed = encoder.finish().unwrap();
        (compressed, "gzip")
    } else if accept_encoding.contains("deflate") {
        // Deflate压缩
        let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default());
        encoder.write_all(content.as_bytes()).unwrap();
        let compressed = encoder.finish().unwrap();
        (compressed, "deflate")
    } else {
        // 不压缩
        (content.as_bytes().to_vec(), "")
    }
}

// 处理HTTP请求
async fn handle_request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    // 要返回的网页内容
    let html = r#"
<!DOCTYPE html>
<html>
<head>
    <title>动态压缩测试</title>
</head>
<body>
    <h1>服务器给你用了最优压缩方法!</h1>
    <p>按F12→网络,看响应头Content-Encoding就知道用了啥~</p>
    <p>内容越长,压缩效果越明显哦~</p>
</body>
</html>
    "#;

    // 获取浏览器支持的压缩方法
    let accept_encoding = req.headers()
        .get(ACCEPT_ENCODING)
        .and_then(|h| h.to_str().ok())
        .unwrap_or("");

    // 选择最优压缩方法
    let (compressed, encoding) = compress_best(html, accept_encoding);

    // 构建响应
    let mut response = Response::builder()
        .header(CONTENT_TYPE, "text/html; charset=utf-8");

    // 添加压缩方式头(如果用了压缩)
    let response = if !encoding.is_empty() {
        response.header(CONTENT_ENCODING, encoding)
    } else {
        response
    }.body(Body::from(compressed)).unwrap();

    Ok(response)
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
    let make_svc = make_service_fn(|_conn| async {
        Ok::<_, Infallible>(service_fn(handle_request))
    });
    let server = Server::bind(&addr).serve(make_svc);

    println!("服务器启动!访问 http://127.0.0.1:8080");
    if let Err(e) = server.await {
        eprintln!("服务器出错:{}", e);
    }
}

步骤 4:编译运行

bash

cargo run



打开浏览器访问http://127.0.0.1:8080,按 F12 查看 “网络” 标签:



  • 现代 Chrome/Firefox 会显示Content-Encoding: br(Brotli,优先级最高)。
  • 如果用较老的浏览器(比如 IE11),可能显示Content-Encoding: gzip。
  • 极端情况(比如禁用所有压缩)会没有Content-Encoding头。

总结:浏览器的 “压缩菜单” 怎么点?

  • 兼容性首选 gzip:像餐厅的 “招牌菜”,几乎所有人都能接受。
  • 追求极致选 Brotli:适合现代浏览器用户,压缩率最高,像 “精致套餐”。
  • 老系统用 Deflate:虽然不常用,但老浏览器可能只认它,像 “怀旧套餐”。
  • 尝鲜选 Zstd:新浏览器支持,平衡速度和压缩率,像 “新品体验套餐”。



实际开发中,服务器通常会按 “Brotli> Zstd > gzip > Deflate” 的优先级选择,既保证多数用户体验,又不抛弃老系统 —— 就像餐厅既卖新品,也保留经典菜~

标题:

  1. 浏览器的 “压缩菜单”:从 gzip 到 Zstd 全解析
  2. 一文看懂:浏览器支持的 4 种网页压缩方法及实战

简介:

本文用快递打包的幽默类比,详解浏览器支持的 4 种网页压缩方法(gzip、Brotli、Deflate、Zstd),通过前端检测页面和后端动态选择案例,展示各方法的特点与使用场景,步骤清晰可实操,助你掌握网页压缩的 “点菜技巧”。

关键词:

#浏览器 #网页压缩 #gzip #Brotli #Zstd

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言