(回顾)性能调优实践 gzip, brotli, https, angular

前端性能优化

标题可能起的有点大,这次是实践是对目前在做的项目的一次性能调优,但是也没有尝试所有方式。

起因是我们的网站被客户吐槽慢。。。

然后开始了性能调优。

gzip实践

服务器端的优化是首先想到的方法,因为这个优化的力度是前端code层面优化比不了的。项目是Angular6的,打包之后用–stats-json和webpack-bundle-analyzer可以看到目前打包之后各个js的大小以及gzip压缩之后的大小,gzip压一压,最少能小一半,有些能压到十分之一。
gzip的原理是在服务器进行配置,对制定类型的文件采用gzip压缩,客户端在获得传输的数据之后再进行解压。通过这个方式可以减少文件传输的时间,但是会增加压缩和解压的时间,所以对于一些很小的文件是不建议启用gzip的(服务器配置的时候也可以设置文件大小)。
配置大概是

LoadModule deflate_module modules/mod_deflate.so AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript

在httpd.conf开启mod_deflate,然后选一下文件类型。

本地build了一个docker测试 => 快得一批!

部署到服务器打开网站 => 没得卵用!又改了几次配置,部署到服务器上都是一样。

开始怀疑gzip,开始怀疑服务器,开始怀疑自己。

  • 问题:本地测试gzip生效,但服务器上相同配置gzip后不生效。
  • 思路:服务器的机器和本地机器肯定有不同,但是两边最终都是build出来docker image,image内的环境配置和安装的软件都是一样的,搜了“gzip不生效”找到的基本是怎么配置gzip -> 两边不同的还有协议,服务器端proxy设置了强制ssl,所有访问都是https本地是http://localhost,搜“gzip https 不生效”找到答案:因为有BREACH(大致是ssl会对文件加密,以保护文件内容不被他人获取和篡改)但是如果引入gzip,hackers可以通过victim的机器发送大量明文请求和压缩算法(gzip 压缩在 HTTP 中的工作方式是这样:如果在响应中有同一个字符串的多个实例,第一个实例将被保留,而其余实例将被替换成指向第一个实例位置的短引用,以减少响应消息的体积)来破解文件内容。=> SSL和gzip不能同时使用(搜索时候找到了一个关于apache的SSLCompression的配置,进行了尝试,无果)

Brotli实践

  • 问题:SSL和gzip不能同时使用,对于我们现有site SSL不能disable => 无法实现服务器端优化?
  • 思路:(看看别人是怎么做的)-> bootstrap,load很快,它也是https,接着看了network,Performance bootstrap文件被压缩过->继续看response头-> 发现:content-encoding: br->搜索“content-encoding br”->找到Brotli是一种类似gzip的压缩算法,接下来就是在server上进行Brotli的配置。
  1. 首先要在httpd.conf配置当中打开mod_brotli,这一步有点类似于gzip打开mod_deflate,然后配置需要压缩的文件类型,配置大概长这样:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    # Load brotli module
    LoadModule brotli_module modules/mod_brotli.so

    <IfModule brotli_module>
    # Output filter
    AddOutputFilterByType BROTLI text/plain text/css text/xml text/javascript application/javascript

    # SetOutputFilter BROTLI
    # SetEnvIfNoCase Request_URI \.txt$ no-br

    # Compression
    ## BrotliCompressionLevel: 0-11 (default: 11)
    BrotliCompressionLevel 10

    ## BrotliWindowSize: 10-24 (default: 22)
    BrotliWindowSize 22

    # Specifies how to change the ETag header when the response is compressed
    ## BrotliAlterEtag: AddSuffix, NoChange, Remove (default: AddSuffix)
    BrotliAlterEtag AddSuffix

    # Filter note
    BrotliFilterNote Input brotli_in
    BrotliFilterNote Output brotli_out
    BrotliFilterNote Ratio brotli_ratio

    LogFormat '"%r" %{brotli_out}n/%{brotli_in}n (%{brotli_ratio}n)' brotli
    CustomLog logs/access_log brotli
    </IfModule>

try -> not work -> docker exec -it container /bin/bash 检查了一下/usr/local/apache2/module里面没有这个mod -> 所以首先要先build出来这个mod

  1. 修改Dockerfile内的build脚本
    1
    2
    RUN git clone --depth=1 --recursive https://github.com/kjdev/apache-mod-brotli.git
    RUN cd ./apache-mod-brotli && sh ./autogen.sh && ./configure && make && install -p -m 755 -D .libs/mod_brotli.so /usr/local/apache2/modules/mod_brotli.so

主要是这两句命令,大概就是clone了brotli的代码然后build出来需要的mod。
中间碰到一个坑,apt-get install的时候需要修改source.list,否则jessie-backports会出错。因为不太懂这个配置文件,中间查了很多关于”Failed to fetch jessie backports repository”这个错的文章,照着改了n多次。最后试下来加了这几句:

1
2
3
4
RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list
RUN echo 'deb http://archive.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/backports.list
RUN echo 'deb-src http://archive.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/backports.list
RUN apt-get -o Acquire::Check-Valid-Until=false update

  1. 安装必须软件
    这步就比较简单,build时候如果报错了把需要的软件装一下。
    1
    2
    3
    4
    5
    6
    7
    RUN ["apt-get", "install", "-y", "git"]
    RUN ["apt-get", "install", "-y", "make"]

    RUN ["apt-get", "install", "-y", "autotools-dev"]
    RUN ["apt-get", "install", "-y", "automake"]
    RUN ["apt-get", "install", "-y", "libtool"]
    RUN ["apt-get", "install", "-y", "apache2-dev"]

到这里Brotli这个module就配置好了。实测网站首页load时间缩短了一半以上。
performance result