前端性能优化
标题可能起的有点大,这次是实践是对目前在做的项目的一次性能调优,但是也没有尝试所有方式。
起因是我们的网站被客户吐槽慢。。。
然后开始了性能调优。
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,
文件被压缩过->继续看response头-> 发现:content-encoding: br->搜索“content-encoding br”->找到Brotli是一种类似gzip的压缩算法,接下来就是在server上进行Brotli的配置。
- 首先要在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
- 修改Dockerfile内的build脚本
1
2RUN 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
4RUN 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
- 安装必须软件
这步就比较简单,build时候如果报错了把需要的软件装一下。1
2
3
4
5
6
7RUN ["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时间缩短了一半以上。