webpack 的 compression-webpack-plugin 就是做这个事情的,配置起来也很简单只需要在装置中加入对应插件,简单配置如下
const CompressionWebpackPlugin = require('compression-webpack-plugin'); webpackConfig.plugins.push( new CompressionWebpackPlugin({ asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp('\\.(js|css)$'), threshold: 10240, minRatio: 0.8 }) )
webpack 打包完成后生成打包文件外还会额外生成 .gz 后缀的压缩文件
那么这个插件的压缩等级是多少呢,我们可以在源码中看到默认的 level 是 9
... const zlib = require('zlib'); this.options.algorithm = zlib[this.options.algorithm]; ... this.options.compressionOptions = { level: options.level || 9, flush: options.flush ... }
可以看到压缩使用的是 zlib 库,而 zlib 分级来说,默认是 6 ,最高的级别就是9 Best compression (also zlib.Z_BEST_COMPRESSION),因为我们只有在上线项目时候才回去打包构建一次,所以我们在构建时候使用最高级的压缩方式压缩多耗费一些时间对我们来说根本没任何损耗,而我们在服务器上也不用再去压缩文件,只需要找到相应已经压缩过的文件直接返回就可以了。
服务端怎么找到这些文件
在应用层面解决这个问题还是比较简单的,比如上述压缩文件会产生index.css, index.js的压缩文件,在服务端简单处理可以判断这两个请求然后给予相对应的压缩文件。以 node 的 express 为例
... app.get(['/index.js','/index.css'], function (req, res, next) { req.url = req.url + '.gz' res.set('Content-Encoding', 'gzip') res.setHeader("Content-Type", generateType(req.path)) // 这里要根据请求文件设置content-type next() })
上面我们可以给请求返回 gZip 压缩后的数据了,当然上面的局限性太强也不可取,但是对于处理这个方面需求也已经有很多库存在,express 有 express-static-gzip 插件 koa 的 koa-static 则默认自带对 gZip 文件的检测,基本原理就是对请求先检测 .gz后缀的文件是否存在,再去根据结果返回不同的内容。
哪些文件可以被 gZip 压缩
gZip 可以压缩所有的文件,但是这不代表我们要对所有文件进行压缩,我们写的代码(css,js)之类的文件会有很好的压缩效果,但是图片之类文件则不会被 gzip 压缩太多,因为它们已经内置了一些压缩,一些文件(比如一些已经被压缩的像.zip文件那种)再去压缩可能会让生成的文件体积更大一些。当然已经很小的文件也没有去压缩的必要了。