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

原文链接原文链接

用户对网页打开速度忍耐值普遍在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 查询和路由跟踪等工具。

https://tool.chinaz.com/sitespeed

IPIP.NET TraceRoute 查询

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

https://tools.ipip.net/traceroute.php

Pingdom Website Speed Test

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

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

<a class="btn" href="/" target="_blank">点击打开</a>

{% endtabs %}

<ad>1</ad>

IP 基准

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

服务商 IP 地址 IP 所在地 延迟 代表 URL
Github Pages 185.199.108.153 北美美国 200ms https://michael728.github.io
CloudFlare 104.27.159.110 北美美国 183ms https://alanlee.fun/
Netlify 157.230.37.202 新加坡 178ms https://infallible-euclid-5f7a7a.netlify.com
腾讯云 58.216.107.77 江苏-常州 14ms https://zzt.bigpar.cn
某香港主机 137.220.134.152 香港 73ms https://wivwiv.com

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

Github Pages
CloudFlare
Netlify
腾讯云
香港某主机

Github Pages CDN 全站加速

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

从结果来看,好像起到了减速 效果,唯一有理有据的一点是 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

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

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

Trace 效果

Github Pages trace 北美美国 200ms
新加坡 DigitalOcean 数据中心 trace

加速前后

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

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

Netlify + CloudFlare 免费 CDN 加速优化

使用 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

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

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

效果比较

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

image

**实际打开效果是杠杠的,相比前几个方案这次有了质的飞越 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
腾讯云 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

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

Trace 效果

新加坡 DigitalOcean 数据中心 trace
香港某主机 trace

加速前后

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

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

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

本文作者: wivwiv
本文链接https://wivwiv.com/post/speed-up-website-loading
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容