博客建立的第一年,我主要采用WP插件的方式优化访问速度,效果不错但是反应速度仍然偏慢,换VPS了正好又是寒假,想着手解决一下这个问题。这篇文章记录了各个阶段使用的方法及其效果。如果想查看本站目前使用的解决方案,直接翻到最后一页即可。
Stage One
- 使用插件:Autoptimize
这款插件功能挺多的,能自动优化HTML/Javascript/CSS。对于兼容性比较好的主题,全部勾上基本没问题了。
然而用完之后,访问速度还是很慢,所以我开始质疑这款插件的效果(后来发现是自己太幼稚了,那台OpenVZ不能开BBR,1G内存而且疑似高度超售,php能跑得快、网速好才怪呢)。
Stage Two
- 使用插件:Autoptimze、Async Javascript、Redis object cache
- <head>修改:preload、preconnect(手动修改)
- 主题文件修改(解决国内Google Font不可用的问题)
后来在折腾缓存的时候,偶然发现Redis可以用来给Wordpress加速(一开始也想搞memcache的,发现这台宝塔面板的机子做个Redis然后给WP装个插件弄起来更方便一点)。
一开始我想不靠这些插件轻装上阵,然而发现Wordpress的臃肿不是闹着玩的,Jetpack这种有免费图像缓存、Downtime监视功能的插件又不能不要,目光又回到了WordPress插件上。
同时在这个阶段我又发现了PageSpeed Insights,可以方便地对网站性能情况进行打分。或者,使用另一款GTmetrix,虽然高峰时期未注册用户要排队测试,但是不像PageSpeed Insights成绩会抽风,而且给出一些莫名其妙让人哭笑不得的优化建议(例如指出Google自家Analytics、AdSense在网页中内嵌的js需要优化等,自己打自己的脸,充分展示了大厂的宫斗风)。
测试过程中又穿插上解决国内google fonts无法使用的问题,根据浏览器页面的html源码(字体名称)在主题php中找到了字体加载路径,在未被墙的主机上下载了字体文件并上传到服务器上,替换掉主题php中的路径,搞定。顺便搞了波
font-display: fallback; ,(虽然对主题中的material-icons并没有什么卵用,但是评测分数提升了一些)。
Preload通俗来说就是告知浏览器,网页会在后面用到一些资源,可以提前进行下载。preload字体的话,直接在<head>里写就行(能插header的插件市场里一堆,就连管广告的Ad Inserter都带个修改header/footer的功能),我参考了这里(这篇文章详细介绍了preload的各种用法),在<head>里插入了下面几行代码:
<!-- 请根据自己站点使用的字体信息编辑如下内容 --> <link rel="preload" href="/wp-content/themes/realistic/font/KFOmCnqEu92Fr1Mu4mxK.woff2" as="font" type="font/woff2" crossorigin/> <link rel="preload" href="/wp-content/themes/realistic/font/KFOlCnqEu92Fr1MmSU5fBBc4.woff2" as="font" type="font/woff2" crossorigin/> <link rel="preload" href="/wp-content/themes/realistic/font/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2" as="font" type="font/woff2" crossorigin/>
此外,还有preconnect,作用是写在<head>里,让客户端提前连接站点,减少加载时间。和下文pagespeed的dns-prefetch有相似之处,但dns-prefetch只是查询DNS,并不连接。
<!-- 域名列表请根据自己的情况填写 --> <link href='https://1.gravatar.com' rel=preconnect /> <link href='https://secure.gravatar.com' rel=preconnect /> <link href='https://adservice.google.com' rel=preconnect /> <link href='https://www.googletagmanager.com' rel=preconnect /> <link href='https://www.googletagservices.com' rel=preconnect /> <link href='https://www.google-analytics.com' rel=preconnect /> <link href='https://pagead2.googlesyndication.com' rel=preconnect /> <link href='https://tpc.googlesyndication.com' rel=preconnect /> <link href='https://stats.wp.com' rel=preconnect /> <link href='https://widgets.wp.com' rel=preconnect /> <link href='https://c0.wp.com' rel=preconnect /> <link href='https://i0.wp.com' rel=preconnect /> <link href='https://i1.wp.com' rel=preconnect /> <link href='https://i2.wp.com' rel=preconnect /> <link href='https://s.wp.com' rel=preconnect /> <link href='https://s0.wp.com' rel=preconnect /> <link href='https://s1.wp.com' rel=preconnect /> <link href='https://s2.wp.com' rel=preconnect /> <link href='https://pixel.wp.com' rel=preconnect /> <link href='https://public-api.wordpress.com' rel=preconnect /> <link href='https://www.gravatar.com' rel=preconnect /> <link href='https://googleads.g.doubleclick.net' rel=preconnect />
详细配置之后,分数从初始40分左右提高到56分(移动端)。扣分项主要还是TTFB和阻塞渲染的时长这两项。
Stage Three
- Nginx模块:ngx_pagespeed(其实pagespeed也有Apache的Module)
- 插件:Redis object cache
- <head>修改:preload、preconnect (手动修改)
用了Cloudflare,56分的成绩在国内某些网络下(没错,说的就是你这个辣鸡联通,就是因为你,Cloudflare成了名副其实的减速CDN)是远远不够用的,还得再找提分点。偶然的机会盯上了pagespeed模块。谷歌出品,必属精品BBR就是谷歌出的一款服务器module,所以想着试试。
Ubuntu 18.04的安装过程(安装前请在此处查看最新版本,推荐使用稳定版):
sudo apt-get install build-essential zlib1g-dev libpcre3 libpcre3-dev unzip uuid-dev
#推荐不要再动除了NPS_VERSION以外的其他内容。 #[check the release notes for the latest version] NPS_VERSION=1.13.35.2-stable cd wget https://github.com/apache/incubator-pagespeed-ngx/archive/v${NPS_VERSION}.zip unzip v${NPS_VERSION}.zip nps_dir=$(find . -name "*pagespeed-ngx-${NPS_VERSION}" -type d) cd "$nps_dir" NPS_RELEASE_NUMBER=${NPS_VERSION/beta/} NPS_RELEASE_NUMBER=${NPS_VERSION/stable/} psol_url=https://dl.google.com/dl/page-speed/psol/${NPS_RELEASE_NUMBER}.tar.gz [ -e scripts/format_binary_url.sh ] && psol_url=$(scripts/format_binary_url.sh PSOL_BINARY_URL) wget ${psol_url} tar -xzvf $(basename ${psol_url}) # extracts to psol/
既然是nginx原来没有的module,当然要下载nginx源码重新编译安装啦,因为我用的宝塔面板,所以找到nginx源码位置/www/server/nginx/src。
cd /www/server/nginx/src #需要查看原来安装的nginx的配置 nginx -V #会出现一些代码,直接复制,然后./configure时在末尾加上--add-module=$HOME/$nps_dir ${PS_NGX_EXTRA_FLAGS} #安装前推荐关闭nginx sudo service nginx stop ./configure --user=www --group=www --prefix=/www/server/nginx --with-openssl=/www/server/nginx/src/openssl --add-module=$HOME/$nps_dir ${PS_NGX_EXTRA_FLAGS} --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-openssl-opt='enable-tls1_3 enable-weak-ssl-ciphers' --with-ld-opt=-ljemalloc --with-cc-opt=-Wno-error make sudo make install #备注:pagespeed也支持以dynamic module的方式被编译及加载,关于dynamic module的详细信息请参考nginx文档。
(其他系统的安装及配置步骤目前从略,请参考此处,现在只贴出部分server部分配置代码,但官方文档指出可以在http部分全局开启,然后各分站点详细配置;更详细的配置选项请参考官网文档。)
警示:请仔细检查下面的配置是否符合站点需要,不正确的配置会导致资源无法访问或者应用运行缓慢。
#启用Pagespeed pagespeed on; #配置共享内存元数据缓存 pagespeed CreateSharedMemoryMetadataCache "/var/ngx_pagespeed_cache/" 51200; # Nginx对于缓存要可写。为了最佳性能,可以使用tmpfs(载入RAM中,不推荐RAM<1G设备使用)。 pagespeed FileCachePath /var/ngx_pagespeed_cache; # 下面几个单位应该分别是KB/毫秒/个吧(CacheSize建议设置为站点总资源大小的5倍) pagespeed FileCacheSizeKb 512000; pagespeed FileCacheCleanIntervalMs 3600000; pagespeed FileCacheInodeLimit 500000; #Redis/Memcached请根据服务器实际,选择性开启,只能二选一。其中Redis支持为实验性功能,有长时间使用后Redis进程无故停止的报告,而且个人测试发现会使WP Super Cache优化的TTFB失效。 #pagespeed RedisServer "127.0.0.1:6379"; #pagespeed MemcachedServers "host1:port1,host2:port2,host3:port3"; # Content-Security-Policy 头部 pagespeed HonorCsp on; # 压缩CSS pagespeed EnableFilters rewrite_css; # 合并CSS pagespeed EnableFilters combine_css; # 内嵌CSS pagespeed EnableFilters inline_css; # Flatten CSS imports pagespeed EnableFilters flatten_css_imports; # 重写CSS,优化加载渲染页面的CSS规则 pagespeed EnableFilters prioritize_critical_css; # 移动CSS至JS之上 pagespeed EnableFilters move_css_above_scripts; # 移动CSS到<head>中 pagespeed EnableFilters move_css_to_head; # google字体直接写入html 目的是减少浏览器请求和DNS查询 pagespeed EnableFilters inline_google_font_css; # 压缩js pagespeed EnableFilters rewrite_javascript; # 合并js pagespeed EnableFilters combine_javascript; # 延迟加载Javascript pagespeed EnableFilters defer_javascript; # 内联Javascript pagespeed EnableFilters inline_javascript; # 限制内联的js文件最大大小,便于大型js文件的静态缓存 pagespeed JsInlineMaxBytes 2560; # 合并heads,只保留一个 pagespeed EnableFilters combine_heads; # 将http-equiv元信息转换成HTTP头 pagespeed EnableFilters convert_meta_tags; # html字符转小写 pagespeed LowercaseHtmlNames on; # 移除 html 空白 pagespeed EnableFilters collapse_whitespace; # 移除 html 注释 pagespeed EnableFilters remove_comments; # DNS 预加载 pagespeed EnableFilters insert_dns_prefetch; # 优化内嵌样式属性 pagespeed EnableFilters rewrite_style_attributes; # 压缩图片 pagespeed EnableFilters rewrite_images; # 不加载显示区域以外的图片 pagespeed EnableFilters lazyload_images; # 禁止在onload事件后立即加载图片(不推荐启用),在极端情况下(如多图页面)可能会导致用户体验极差 #pagespeed LazyloadImagesAfterOnload off; # 图片预加载 pagespeed EnableFilters inline_preview_images; # 移动端图片自适应重置 pagespeed EnableFilters resize_mobile_images; # 响应式图像,需启用rewrite_images pagespeed EnableFilters responsive_images; # 增强响应式图像的功能,在用户放大时加载高分辨率图像。此项启用后会在页面内自动插入一段js以实现功能 #pagespeed EnableFilters responsive_images_zoom; # 雪碧图片,图标很多的时候很有用 pagespeed EnableFilters sprite_images; # 扩展缓存 改善页面资源的可缓存性 pagespeed EnableFilters extend_cache; pagespeed XHeaderValue "Powered By ngx_pagespeed"; pagespeed SupportNoScriptEnabled false; # admin直接访问<域名>/pagespeed_admin 就可以打开管理员界面了。 pagespeed Statistics on; pagespeed StatisticsLogging on; pagespeed LogDir /var/log/pagespeed; pagespeed AdminPath /pagespeed_admin; pagespeed GlobalAdminPath /pagespeed_global_admin; # 缩写站内链接地址 pagespeed EnableFilters trim_urls; # 复用页面内已经加载过的图片 pagespeed EnableFilters dedup_inlined_images; # 当属性值等于默认值时,移除HTML文件中的这些值,减少流量且便于压缩 pagespeed EnableFilters elide_attributes; # 提示浏览器提前加载用到的JS/CSS pagespeed EnableFilters hint_preload_subresources; # 去除HTML中不必要的引号 pagespeed EnableFilters remove_quotes; # 去除HTML中的注释 pagespeed EnableFilters remove_comments; # 将对噪声敏感的非动画GIF/PNG转换为无损WebP pagespeed EnableFilters convert_to_webp_lossless; # 将动画GIF转换为WebP pagespeed EnableFilters convert_to_webp_animated; # 将静态GIF转换为PNG pagespeed EnableFilters convert_gif_to_png; # 将非噪声敏感的PNG转换为JPG pagespeed EnableFilters convert_png_to_jpeg; # 将非噪声敏感的JPG转换为WebP pagespeed EnableFilters convert_jpeg_to_webp; # 允许清空缓存 pagespeed EnableCachePurge on; # 无视no-transform,进行优化 pagespeed DisableRewriteOnNoTransform off; # 优化JS引用的图片,注意可能会导致一些问题,如果有大量错误日志建议关闭 pagespeed InPlaceResourceOptimization on; pagespeed EnableFilters in_place_optimize_for_browser; # 设置LoadFromFile,直接从服务器本地加载文件,避免了模拟http访问时遇到的各种Cache Control问题 # 需要针对自己服务器的静态资源情况进行修改 pagespeed LoadFromFile "https://foo.yourdomain/virtual_path" "/path/to/your/real/resources"; # pagespeed的EnableFilters是支持用","连接的,在nginx里可以写在http{}部分,只占用一行空间,且不用在server{}内重复配置,更为清爽。
警示:对于部分网页,上述功能全开会出现问题,需要详细调试加以排除。
然后我停用了插件,发现自己还是too young, too simple……几乎没什么卵用,阻塞渲染的资源还是那几个JS和死活搞不定的CSS。