Brotli压缩算法在WEB中的应用 | 最佳实践

1,446 阅读4分钟

摘要:Brotli与Gzip类似,是构建包压缩算法的一种,本文通过docker实战部署nginx brotli服务,详细说明brotli在web中的应用和效果。

关键词: 大前端  web性能优化 brotli brotli容器化部署 docker

一、目的:

Vue 等MVC框架的前端项目常因框架或第三方包的原因,导致构建包比较大,增加首屏加载时长和用户等待白屏时间,本文介绍Brotli压缩技术在web中的实践,进一步减少构建包大小,提升web网站性能和用户体验。

二、Brotli是什么:

2015 年 9 月 Google 推出了无损压缩算法 Brotli。Brotli 通过变种的 LZ77 算法、Huffman 编码以及二阶文本建模等方式进行数据压缩,与其他压缩算法相比,它有着更高的压缩效率。

三、浏览器的支持:

目前Brotli已经被绝大多数浏览器支持,除IE和Opera Mini浏览器,ios浏览器11版本开始支持,在使用时需注意不支持版本兼容的处理。

image.png

四、Brotli与其他压缩算法效果对比:

压缩算法在不同level下的比较(数据摘自网络):

image.png

压缩算法对从 Internet 爬网的文档样本的结果,该示例包含 1285 个 HTML 文档:

image.png

项目实际情况:

image.png

a)  质量级别为11的 Brotli压缩效果明显优于Gzip,压缩率高出 20% ~ 26%。

b)  质量级别为6的Brotli,综合效果最优,其压缩效果、压缩速度、解压速度基本超过Gzip。

c)  质量级别比较高时,其压缩速度明显低于Gzip,不太适合大文件的动态的压缩。

五、docker部署实战:

1、docker容器化部署:

nginx version 1.18.0,Docker version 18.06.1-ce,建议使用nginx1.18版本,低版本不支持动态编译。

// docker nginx 安装
docker pull nginx:1.18.0
docker images nginx
// 启动服务
docker run --name nginx-test -p 9002:80 -d nginx:1.18.0
// 设置关联
mkdir /etc/nginx-test
cd /etc/nginx-test
mkdir log
mkdir www
mkdir config
// id为容器id
docker cp id:/etc/nginx/nginx.conf   /etc/nginx-test
docker cp id:/etc/nginx/conf.d/.   /etc/nginx-test/config
docker cp id:/usr/share/nginx/html/. /etc/nginx-test/www/
// 删除此容器,在重新起一个
docker stop id
docker ps
docker rm id
docker run --name nginx1.18 -p 9002:80 -v /etc/nginx-test/nginx.conf:/etc/nginx/nginx.conf -v /etc/nginx-test/www/:/usr/share/nginx/html/ -v /etc/nginx-test/log/:/var/log/nginx/ -v /etc/nginx-test/config/:/etc/nginx/conf.d --privileged=true -d nginx:1.18.0

2、生成nginx_brotli编译文件

     下载ngx_brotli

// 下载ngx_brotli
git clone https://github.com/google/ngx_brotli.git
// 进入ngx_brotli目录下的deps文件夹,下载brotli
cd /etc/ngx_brotli && git submodule update --init

       接下来下载nginx1.18版本注意与docker安装版本一致,否则可能会导致编译的文件无法使用

// 下载nginx1.18
wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar -xvf nginx-1.18.0.tar.gz
cd nginx-1.18.0
// 编译生成brotli的 .so文件
./configure --with-compat --add-dynamic-module=/etc/ngx_brotli
make modules
// 参数语法:--add-dynamic-module=[模块源码所在目录的绝对路径]
// 查看生成文件
ls objs/*.so
// 输出这个2个文件 objs/ngx_http_brotli_filter_module.so  objs/ngx_http_brotli_static_module.so

3、将编译好的模块文件复制到docker nginx关联文件目录下

// 在关联目录www目录下 新建modules目录 放入编译的brotli so文件
sudo cp objs/{ngx_http_brotli_filter_module.so,ngx_http_brotli_static_module.so} /etc/nginx-test/www/modules

4、docker nginx配置

...
//  注册brotli
load_module /usr/share/nginx/html/modules/ngx_http_brotli_filter_module.so;
load_module /usr/share/nginx/html/modules/ngx_http_brotli_static_module.so;
...
http {
...
    server {
      #listen 80;
      listen 443 ssl http2 ;  // 注意brotli只支持https协议
      server_name 域名;
      ssl_certificate /usr/share/nginx/html/cert/elsttest2.sinewave.top.cert.pem;
      ssl_certificate_key /usr/share/nginx/html/cert/elsttest2.sinewave.top.key.pem;
      location / {    
        root /usr/share/nginx/html/teacher;
        index index.html;
      }
     // 保留gzip 是为了兼容不支持brotli的浏览器
     gzip on;
     gzip_buffers 32 4K;
     gzip_comp_level 6;
     gzip_min_length 100;
     gzip_types application/javascript text/css text/xml;
     gzip_disable "MSIE [1-6].";
     gzip_vary on;
    // 配置brotli
     brotli on;
     brotli_static on;
     brotli_comp_level 6;
     brotli_buffers 16 8k;
     brotli_min_length 20;
     brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript 
image/svg+xml application/octet-stream;
    }
}

5、前端生成brotli构建包

vue.config.js文件

const CompressionWebpackPlugin = require('compression-webpack-plugin')
configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config.plugins.push(
        new CompressionWebpackPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: /.js$|.html$|.css/,
          threshold: 2048,
          minRatio: 0.8
        }),
        new CompressionWebpackPlugin({
          filename: '[path].br',
          algorithm: 'brotliCompress',
          test: /.(js|css|html|svg)$/,
          threshold: 10240,
          minRatio: 0.8,
          compressionOptions: {
            level: 11,
          }
        })
      )
   }
}

image.png

6、打包文件至docker>nginx>www>teacher文件下,重启nginx

// id 为容器id
docker ps
docker stop id
docker restart id

验证brotli是否成功

image.png

六、项目实际效果评估:

测试环境:

image.png

brotli可提升web首屏加载速度20%+,网速越慢构建包越大提升效果越明显,浏览器兼容性良好,建议学习储备。