前端性能优化之文件压缩gzip zopfli及brotli

4,893 阅读2分钟

通常我们前端压缩一般用前端的脚手架build一下就好了,觉得已经代码压缩了,很少再做其它压缩了。其实还有更强的压缩方式。打开淘宝京东看一下他们

image.png

image.png

以前听过,知道些,究竟怎么实现... 看到了就想做出来,接下了自己就测试了一番。

gzip

  • 服务器配置: 浏览器请求文件时,服务器对文件进行gzip压缩后传输给浏览器。前端不用做任何修改正常打包,但这样消耗服务器性能,比如Nginx开启gzip压缩,配置文件加一下内容
    gzip  on;
    gzip_buffers 4 16k;
    gzip_comp_level 6;
    gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php;

重启Nginx即可

  • 前端打包: 打包的时候通过webpack配置生成对应的 .gz 文件,浏览器请求文件时,服务器返回对应的.gz文件;这样就节省了服务器的消耗。

前端打包借助webpack插件 compression-webpack-plugin

npm install compression-webpack-plugin --save-dev

打包配置以Vue项目为例

vue.config文件添加

const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
    configureWebpack: {
        plugins:[
            new CompressionPlugin({
                algorithm: 'gzip',
                test: /\.js$|\.html$|\.css$/,
                filename: '[path].gz[query]',
                minRatio: 1,
                threshold: 10240,
                deleteOriginalAssets: false,
            })
        ]
   }
}

如果打包提示插件出错就降低插件版本,我降到5.0才正常:"compression-webpack-plugin": "^5.0.0",

服务器Nginx配置添加

gzip_static on;

重启即可。

如果配置验证失败需要添加--with-http_gzip_static_module模块 我是编译安装Nginx,步骤如下

  • nginx -V 会显示出编译的配置在配置里添加 --with-http_gzip_static_module,注意V的大小写,小写只显示版本号
--prefix=/usr/nginx --with-http_ssl_module --with-openssl=/root/openssl-1.1.0h --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --user=nginx --group=nginx
  • 进入到nginx源码目录重新编译

image.png

  • 然后meke 好了之后会在源码目录下的objs目录产生nginx的二进制,先不要make install(make install,否则直接覆盖了)

image.png

  • 然后把原先的nginx二进制命令备份,用上面编译好的nginx替换,最后reload的nignx就可以
[root@oyy sbin]# mv nginx nginx.bak      #备份
[root@oyy sbin]# cp /root/nginx-1.12.2/objs/nginx .  #把编译好的nginx拷贝过来
[root@oyy sbin]# nginx -s reload    #重载

如果没生效就完全退出Nginx重启nginx

[root@oyy sbin]# nginx -s quit
[root@oyy sbin]# nginx

再 nginx -V看到有对应的模块就对了

那么浏览器怎么看有无成功使用了gzip压缩呢

打开可控制台

accept-encoding代表浏览器可接受的压缩类型

content-encoding代表使用的压缩方式

etag如果有W/就是服务器在线压缩,如果没有W/就是打包生成的.gz文件

WX20210525-163140.png

WX20210525-172343.png

zopfli

zopfli压缩后打包的文件格式跟gzip是一样的,压缩率高了一些,小了一点,然后因为打包之后文件格式与gzip一致,所以nginx配置方面跟gzip是一样的.

需要再加一个插件 npm install @gfx/zopfli --save-dev

Vue配置如下

const CompressionPlugin = require('compression-webpack-plugin');
const zopfli = require('@gfx/zopfli');
module.exports = {
    publicPath: '/vue-visual-editor/',
    outputDir: 'docs',
    configureWebpack: {
        plugins:[
        new CompressionPlugin({
                filename: '[path].gz[query]',
                test: /\.js$|\.css$|\.jpg$/,
                threshold: 10240,
                deleteOriginalAssets: false,
                minRatio: 0.8,
                algorithm (input, compressionOptions, callback) {
                  return zopfli.gzip(input, compressionOptions, callback)
                }
            })
        ],
    }
}

比gzip小一点差别不是很大

image.png

brotli

Brotli是最初由Google开发的一种压缩算法,其压缩性能优于gzip。

对比参照上图.br结尾的既是brotli压缩后的文件。压缩率最高

这个依赖zlib模块,这个不用装node里就有,但要Node 10.16.0 以后

vue 配置如下

const CompressionPlugin = require('compression-webpack-plugin');
const zlib = require("zlib");
module.exports = {
    publicPath: '/vue-visual-editor/',
    outputDir: 'docs',
    configureWebpack: {
        plugins:[
            new CompressionPlugin({
                filename: "[path].br",
                algorithm: "brotliCompress",
                test: /\.(js|css|html|svg)$/,
                compressionOptions: {
                  params: {
                    [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
                  },
                },
                threshold: 10240,
                minRatio: 0.8,
            }),
           ],
    }
}

这个服务器配置有一点麻烦

进入服务器克隆

# git clone https://github.com/google/ngx_brotli.git
# cd ngx_brotli
# git submodule update --init

重新编译Nginx,方法如上,在配置文件里添加--add-module=/root/ngx_brotli,“/root/ngx_brotli”这个是自己对应的ngx_brotli目录。 nginx.conf里添加 brotli_static on;把打包后的.br文件传到服务器,重启nginx即可。 验证

WX20210525-222151.png

看到这里我就安心的回去睡觉了。

知识只用自己用了、实现了、看到了效果才觉得自己明白了。

参考资源ngx_brotli,webpack插件