网站10倍速度优化比较 —— CDN gulp压缩 cloudflare js/css分离 Hexo 加速

(Hexo/Hugu 速度优化)用户对网页打开速度忍耐值普遍在3-12秒之间(参照网页打开速度的心理学),超时后用户往往会直接关闭网页并且不想再次访问。

别以为你的网站很快。

本文适用于未备案域名或者使用国外主机/空间的站点加速。如果你的域名已经备案,就算是用的 1MB 小水管,国内有很多免费 CDN 可以使用,本着“一力降十会”、“力大飞砖”等指导思想,你的网站打开速度一般都不会慢。

本站速度优化辛酸史

  • Github Pages 使用 CDN 全站加速
  • 告别 Github Pages,Netlify 静态博客托管
  • Netlify + CloudFlare 免费 CDN 加速优化
  • 使用 Gulp 压缩页面静态资源
  • hexo-neat 压缩页面
  • 使用脚本分离 js/css 实现国内 CDN 局部加速
  • 加钱!迁移到低价收费香港空间

本文仅从资源加载速度方面进行优化,JS 代码优化与执行不在讨论之列。

经过一系列神乎其神的优化之后,相比之前的纯托管在 Github Pages 上,现在MindSpark打开速度提高了10倍!本文讲解几个阶段中的原理步骤比较了几个优化项的效果。

别以为你的网站打开很快

站长的几大幻觉之一就包括 “我的网站打开很快”,这个幻觉是最致命的。网站打开速度是网站质量的直观体现,你的打开速度快不快由你的访问用户尤其是首次访问用户说了算,几个优化路径非常重要:

你的网页页面加载资源大小、数量要合理

  • 优化资源数量,每个资源的加载都需要消耗 DNS 解析、网络请求、HTTP 请求头等一系列不必要的时间和空间
  • 压缩 HTML 与 js/css 中的空格、换行内容以及对机器渲染执行无关的内容可以有效减少文件大小
  • 文本内容是可以高度压缩的,启用 HTTP GZIP 压缩可以减少 3-10 倍的传输大小

影响网站打开速度的重要因素是资源加载速度
一般来说,根据路由转发流程资源距离用户越远,打开越慢。在资源数量体积无法减小的情况下最好的优化方式就是把资源放得距离用户足够近,使用 CDN 技术可以解决问题

  • CDN 技术存在预热与分发过程,用户所在地未完成有效分发之前很慢
  • CDN 服务商也存在优劣之分,节点分布、CDN 网络质量与传输都有很大关系
  • 出于监管需要,国内未在相关备案的网站无法使用国内 CDN 加速(备案很麻烦)

缓存机制
浏览器普遍有缓存机制,资源的缓存策略很重要,绝大多 Web 服务器、CDN 服务商都有缓存配置,但用户首次访问需完整加载一次,后续才优先使用缓存

站长们打开自己的网站很大程度是因为网站已经有本地缓存、CDN 也有预热才觉得快。真正的速度应当是清空缓存后重新打开或让远方的网友打开测试的速度。

网站测速工具

网站打开速度已经成为 SEO 重要的排名依据,除了上面说到的人肉测试,就面向国内用户 + 加载速度测试场景而言,推荐以下三款工具:

站长工具 网站速度测试

针对国内资源加载、网站速度测试。包括 Ping 检测、国内外多监测点网速测试、网站速度对比、DNS 查询和路由跟踪等工具。

点击打开

IPIP.NET TraceRoute 查询

IPIP.NET 是一家专注 IP 地理位置以及 IP 画像数据的研究、整理与发行的数据公司,提供 TraceRoute 等一系列 IP 相关的在线工具。
使用 Trace 的方式可以查看用户到站点的路由信息,一般来说跳数越少打开速度越快,选择 IPIP.NET 是因为其 TraceRoute 提供了可视化的效果,一眼看清问题所在。

点击打开

Pingdom Website Speed Test

知名的网站测速工具,相比 Google PageSpeed Insights 不能指定测速节点,它可以指定从全球数个节点发起测试请求,更贴近你的用户群体。

亚洲这边只有东京区域,四舍五入一下我选择东京区域来测试好了。

点击打开

IP 基准

由于几个优化点使用了 CDN 技术,域名解析得到的实际 IP 地址以 CDN 服务商分配为准,因此本文选择武汉电信作为访问起点来获取 IP,得到下表:

服务商IP 地址IP 所在地延迟代表 URL
Github Pages185.199.108.153北美美国200mshttps://michael728.github.io
CloudFlare104.27.159.110北美美国183mshttps://alanlee.fun/
Netlify157.230.37.202新加坡178mshttps://infallible-euclid-5f7a7a.netlify.com
腾讯云58.216.107.77江苏-常州14mshttps://zzt.bigpar.cn
某香港主机137.220.134.152香港73mshttps://wivwiv.com

使用 TraceRoute 进行测试,测试线路线路结果如下:

Github Pages CDN Hexo 全站加速

GitHub Pages 是 GitHub 静态网站免费托管服务,普遍用来存放个人博客、开源软件文档等站点,支持 Jekyll、Hexo、Hugo 等静态编译的博客。

Gihub 提供免费的子域名 *.github.io 开头,也支持自定义为你的个性化域名,你只需要把文档写到 Github 仓库里,编辑,推送文档更改就会生效在网站上显示。

使用 CDN 加速需要你拥有自己的域名及 CloudFlare 账号,Github Pages 自定义域名比较简单,CloudFlare 也比较容易配置,详细步骤不再赘述推荐查看:

Github Pages 免费使用 SSL 以及 CDN 加速

效果比较

由于教程写的比较晚,我的 Github Pages 站点已经关了,因此我使用 Michael翔 这个站点作为 Github Pages 未加 CDN 的测速站点,使用 Lee’s Space Station 作为已加 CDN 的测试站点。

image-20200308200204034

从结果来看,好像起到了减速 效果,唯一有理有据的一点是 CloudFlare 没有超时地区。

这不科学,我本地的感官上打开速度明显后者比前这快一些,要知道国内 Github 有时候是直接打不开的(超过 12 秒)。可能是最近 CloudFlare 被国人出墙党薅羊毛太多,纸面数据并不咋滴 P:) 。

Trace 效果



Github Pages trace
北美美国 200ms


CloudFlare
北美美国 183ms

加速前后

优点缺点
加速效果明显(感观上)需要有自定义域名
感观上提速 50%局部地区还是比较慢,尤其 DNS 解析

告别 Github Pages,Netlify 静态博客托管

Netlify 是一家旧金山公司,为静态站点提供托管服务及无服务(Serverless)后端服务,它提供免费计划和付费计划。

同样是静态托管,Netlify 还提供了 CI/CD 操作,因此将网站从 Github Pages 迁移到 Netlify 并没有太多技术负担,相关教程见 手把手教你使用Netlify部署博客及部署自动化

风评说 Netlify 国内比较悲催,迁移之前我就在想一个正经的专门做托管服务的公司,再差的免费产品都比 Github Pages 好吧

效果比较

实际测试结果如下,同样是使用表格中的 URL,实际使用体验好,但是纸面数据 Github Pages 还是比 Netlify 更胜一筹:

image-20200308220226280

有一点奇怪,由于绑定 Netlify 是通过 CNAME 解析的,自带 CDN 效果,但是没有国内节点,国内访问到最近的一个节点是托管在新加坡 DigitalOcean 数据中心。

我个人是不怎么看好 DigitalOcean 的,毕竟官网都卡。 P:)

Trace 效果



Github Pages trace
北美美国 200ms


新加坡 DigitalOcean 数据中心 trace
新加坡 DigitalOcean 数据中心

加速前后

其实 Netlify 有些节点 CDN 服务商是 CloudFlare,由于没有国内包括香港节点,连西太平洋一票大陆最优节点都没有,姑且认为 Netlify 的效果跟 Github Pages + CloudFlare 一样吧。

优点缺点
加速效果明显(感观上)需要有自定义域名
感观上提速 50%局部地区还是比较慢
无需自定义域名
支持 CI/CD 自动编译,SPA 网站托管等一些黑科技

Netlify + CloudFlare 免费 CDN Hexo 加速优化

使用 Netlify 作为源站,CloudFlare 作为 CDN 服务商进行加速。

老早我就看明白根据 CDN 的加速原理,虽然源站速度也是一个重要因素影响因素,但是 CloudFlare CDN 节点到 Github Pages 节点走的是纯国外线路,跟到 CloudFlare 到 Netlify 是一样的效果,但是本着追求速度的原则我还是蠢呼呼的用了这个方案。

直到前不久我才发现问题所在,这特么是马车运马,两者的速度都是短板互相拖累,甚至有减速效果。

效果比较

Netlify 裸连跟 CloudFlare 加速就是半斤八两,既没有达到将节点拉的离用户足够近,又没有其他黑科技,因此这个加速我姑且认为没有效果。

“加速”前后

CloudFlare 还是有很多比如合并 js,worker,HTTP2 等等黑科技的,但是于国内加速用处不大。

优点缺点
一定的加速效果(心理上)有一定减速效果
套壳保护源站(心理上)

使用 Gulp 压缩页面静态资源

Gulp 是比较知名的前端自动化工具,早些年很流行我记得我刚接触前端自动化就是这一套,后面市场份额被 Webpack 抢占了很多。

Gulp 集成其他开源包如 uglify imagemin 一众小工具提供开箱即用的 Gulp 系列插件,通过丑化(压缩)浏览器不必要的元素,改变图片格式等方式保证渲染效果的同时实现减小资源大小,效果比较显著,视代码和图片情况平均能减少 20%~80% 的资源大小。

Gulp 压缩工作原理简单,以下提供压缩前后的两段代码,可见压缩有的 js 从三行变为一行,去掉了不必要的空格和换行,实际丑化压缩效果不仅于此:

// 压缩前
for (var i = 0; i <= 100; i++) {
tabs.push(document.querySelect('id-' + i))
}

// 压缩后
for(var i=0;i<=100;i++){tabs.push(document.querySelect('id-'+i))}

效果比较

以 Hexo 生成的站点 HTML 为例,大概 20 篇文章压缩前整个站点大小有 6.6 MB,压缩后站点大小为5.1 MB,如果把减小的体积单纯的算到传输带宽头上,相当于实现了14% 的提速。

嗯?相当于大多数程序员的一年涨薪幅度。

实现步骤

需要 Node.js 环境以及以下依赖:

yarn add gulp gulp-minify-css gulp-uglify gulp-htmlmin gulp-htmlclean gulp-imagemin -D

新建 gulpfile.js 文件,最后通过 Node 执行即可压缩:

var gulp = require('gulp');
var minifycss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
var htmlmin = require('gulp-htmlmin');
var htmlclean = require('gulp-htmlclean');
var imagemin = require('gulp-imagemin');

// 压缩html
gulp.task('minify-html', function () {
return gulp.src('./public/**/*.html')
.pipe(htmlclean())
.pipe(htmlmin({
removeComments: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
}))
.pipe(gulp.dest('./public'))
});
// 压缩css
gulp.task('minify-css', function () {
return gulp.src('./public/**/*.css')
.pipe(minifycss({
compatibility: 'ie8'
}))
.pipe(gulp.dest('./public'));
});
// 压缩js
gulp.task('minify-js', function () {
return gulp.src('./public/js/**/*.js')
.pipe(uglify())
.pipe(gulp.dest('./public'));
});
// 压缩图片
gulp.task('minify-images', function () {
return gulp.src('./public/images/**/*.*')
.pipe(imagemin(
[imagemin.gifsicle({ 'optimizationLevel': 3 }),
imagemin.jpegtran({ 'progressive': true }),
imagemin.optipng({ 'optimizationLevel': 7 }),
imagemin.svgo()],
{ 'verbose': true }))
.pipe(gulp.dest('./public/images'))
});
// 默认任务
gulp.task('default', gulp.parallel(
'minify-html', 'minify-css', 'minify-js', // 'minify-images'
));

“加速”前后

就我个人感觉效果不明显,可能是我的站点比较小,内容比较少。

优点缺点
效果明显可见人类调试、阅读不容
减少存储空间需求需要额外的处理步骤

hexo-neat 压缩页面

如果你的站点是 Hexo 静态站点,这个效果和 Gulp 压缩一样的,只是这个插件做了封装。

实现步骤

安装插件

yarn add hexo-neat

修改站点配置文件 _config.yml,添加以下内容:

neat_enable: true
# 压缩html
neat_html:
enable: true
exclude:
# 压缩css
neat_css:
enable: true
exclude:
- '**/*.min.css'
# 压缩js
neat_js:
enable: true
mangle: true
output:
compress:
exclude:
- '**/*.min.js'
- '**/jquery.fancybox.pack.js'
- '**/index.js'

最后使用 server 模式或者生成的时候编译时可以看到类似的输出即表明启用:

INFO  neat the html: undefined [ 1.00% saved]
INFO neat the html: undefined [ 1.00% saved]
INFO neat the html: undefined [ 1.00% saved]

使用脚本分离 js/css 实现国内 CDN 局部加速

国内的大多数如腾讯云 CDN 有一定的免费额度,本站目前每月享受免费 10GB 流量,对于个人站点绰绰有余,奈何腾讯云 CDN 需要域名”备案”,无法直接加速。

这么好的资源放着就是放着,太浪费了,后来再折腾 Netlify + CloudFlare 加速的阶段,看到 CloudFlare 黑科技把 js 压缩了,我突然想到一个问题:

  • html 文件必须从目标域名即 wivwiv.com 中加载,否则无法访问网站
  • js css 图片等可以跨域加载,如果能把资源传到国内的服务器上,这部分就从国内就近加载了
  • html 文件体积一般比较小,恰巧 js 与 css 文件特别大,效果肯定很显著

所以最终可以得到这么一个思路,将打包后的 css 与 js 以及图片资源上传到腾讯云 CDN 上,搭建专属的 CDN,整个架构如下:

image-20200304210359419

此方式适用于以下条件的站长

  • 网站在国外,用户在国内,但国内访问速度一般,需要国内 CDN 加速的
  • CDN 加速后效果显著的
  • 域名没有备案,不能使用国内 CDN 服务商加速的
  • 使用国外比较好的 CDN 服务商感觉不够性价比的

效果比较

仅从加载速度来看,全国大部分地区是碾压的,如果站点 html 加载不耽误太多时间,html 加载完成之后到了资源加载阶段就变成了国内 vs 国外的状态:

image-20200308230502018

实际打开效果是杠杠的,相比前几个方案这次有了质的飞越 P:)

实现步骤

以下提供腾讯云 COS 上传脚本

  • 找出所有的 HTML 文件
  • 使用 cheerio 用 jQuery 的方式处理 HTML 中的 script 和 link 标签,绕开使用正则
  • 提取、上传 script link 和本地图片地址,上传到 COS 上获得 CDN 绝对地址并替换
// _script/cos-upload.js

const glob = require('glob')
const cheerio = require('cheerio')
const fs = require('fs')
const path = require('path')

const cos = require('./upload');

// url 前缀
const cdnPrefix = 'wivwiv-static'
// 域名全名
const cdn = 'https://cdn.example.cn/wivwiv-static'
const entry = path.join(__dirname, '../public')
const fileMap = {}

async function run() {
// 获取 COS 上现有文件,避免重新上传
const fileList = await cos.getFileList(cdnPrefix);
// { md5: filename }
fileList.forEach(file => {
fileMap[file.ETag.replace(/"/gim, '')] = file.Key
})

// 开始运行
start()
}

run()


function start() {
// 找出所有 html 文件
const htmls = glob.sync(`${entry}/**/**.html`)

// 处理本地 script
htmls.forEach(async html => {
const content = fs.readFileSync(html).toString()
const $ = cheerio.load(content)
const scripts = $('script')
scripts.each(async (i, el) => {
const src = $(el).attr('src')
if (isAbost(src)) {
$(el).attr('src', cdn + src)
await getFile(src)
}
})

// 处理本地 link style
const styles = $('style')
styles.each(async (i, el) => {
const href = $(el).attr('href')
if (isAbost(href)) {
$(el).attr('href', cdn + href)
await getFile(src)
}
})

// 处理本地 图片
const imgs = $('img')
imgs.each(async (i, el) => {
const src = $(el).attr('src')
if (isAbost(src)) {
$(el).attr('src', cdn + src)
await getFile(src)
}
})
const t = $.html()
fs.writeFileSync(html, t)
})
}

function isAbost(src) {
return src && !src.startsWith('http') && !src.startsWith('//');
}

async function getFile(src) {
src = src.split('?')[0]
const f = path.join(entry, src);
const fname = `${cdnPrefix}${src}`
const content = fs.readFileSync(f).toString()
const hash = cos.md5(content)
// 存在且同名
if (fileMap[hash] && fileMap[hash] === fname) {
console.log('不上传')
return;
}
// 上传
await cos.putFile(f, fname);
fs.unlinkSync(f)
console.log(`上传完成: ${fname} ${fileMap[hash]}`)
}

Trace 效果



新加坡 DigitalOcean 数据中心 trace
新加坡 DigitalOcean 数据中心


腾讯云 CDN trace
跨省 江苏-常州

加速前后

加速效果显著,相当于优化了资源数量(源站仅加载 HTML 文件)、加载速度。

优点缺点
加速效果十分明显需要有国内已备案域名

有用 npm + jsDelivr 托管静态资源的方案,这个思路不错,后期我试一试。jsDelivr 测速跟腾讯云 CDN 有得比,jsDelivr 已经拿到 ICP 牌照,中国节点 2015 年就上线了,很可观。

加钱!迁移到低价收费香港空间

看到这一步你应该明白了哪怕只从国外站点加载 HTML 还是有很慢的时候,真羡慕国内的站点,力大飞砖不用优化打开速度也飕飕的。

无论是 Netlify 还是 CloudFlare 在晚间的时候 DNS 解析这一关就不合格,以 CloudFlare 免费 DNS name server 为例,打开 CloudFlare 加速的网站时需要先从 ken.ns.cloudflare.com 查询域名的 URL,而晚间时段这个 ns 丢包 30%,速度全国一片黄!

有时候首页 html 文件打开需要 2~3s,无论什么原因,DNS 解析速度慢这个都是过不去的坎,最终经过评测与挑选后,我选择了香港一个收费空间,每月 2 元安安心心用着,写了个检测脚本,如果哪天跑路了我切回去 Netlify 也不迟。

效果比较

香港线路只要不是流量特别大、特别绕的都没有问题,毕竟同属于一个中国,WIFI 信号都能票过来大陆。

image-20200309000247620

实际打开效果是杠杠的,相比前几个方案这次有了比较大的飞越,毕竟出钱了。

Trace 效果



新加坡 DigitalOcean 数据中心 trace
新加坡 DigitalOcean 数据中心


香港某主机 trace
香港 73ms

加速前后

如果网站比较大,资源数量比较多还要兼顾国内大部分地区访问,放弃 CloudFlare 和 Netlify 吧,从 CNAME 解析一开始你就输了。

优点缺点
加速效果明显(感观上)要花钱(一点点)
有一定后端和数据库能力要提防跑路
要防止 IP 被 K 波及自身
要防止数据丢失

这些问题对于使用 Github 的我都不大,所以我折腾这么多到底是图个啥,图省香港主机的那几块钱?

后面出一篇本站的迁移记录,话说有什么比较好的空间稳定推荐的吗?