目录

加快GitHub Pages国内访问速度

前言

相信不少小伙伴都在使用 GitHub Pages 提供的免费静态网站托管来搭建自己的博客,但是因为墙的存在和特殊国情,使用 GitHub Pages 搭建的网站速度普遍不快,因此很多小伙伴只能转战国内付费的服务器和 CDN。

正巧我也在使用 GitHub Pages 搭建自己的静态博客,正好来说一下我的优化方法。

压缩

默认情况下,如果我们查看 Hexo 生成的静态网页源代码,会发现存在大量的空格、空行、注释等无用内容。同样的,如果使用的 hexo 主题没有进行优化,大量的 css 和 js 文件也存在这样的垃圾内容。

如果你在一些大型网站右键查看网页源代码,你会发现他们的 html\js\css 是经过压缩处理的,没有多余的换行和注释,这势必会节省带宽流量和传输时间,提升用户体验。

所以我们优化速度的第一关就是对 Hexo 生成的代码进行压缩。

这里我使用的工具是 gulp

安装 gulp

在自己本机安装

1
npm install gulp -g

为了 GitHub Action 或其他 CI\CD 平台也能够进行安装,这里推荐

1
npm install gulp --save-dev

我们还需要一些依赖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
npm install --save-dev \
            gulp-minify-css \
            gulp-babel \
            gulp-uglify \
            gulp-htmlmin \
            gulp-htmlclean \
            gulp-imagemin \
            imagemin-jpegtran \
            imagemin-svgo \
            imagemin-gifsicle \
            imagemin-optipng

创建配置文件

在博客 hexo 的根目录下,新建 gulpfile.js 配置文件

 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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");

// 压缩css文件
gulp.task("minify-css", function () {
  return gulp
    .src("./public/**/*.css")
    .pipe(minifycss())
    .pipe(gulp.dest("./public"));
});

// 压缩html
gulp.task("minify-html", function () {
  return gulp
    .src("./public/**/*.html")
    .pipe(htmlclean())
    .pipe(
      htmlmin({
        collapseWhitespace: true,
        collapseBooleanAttributes: true,
        removeComments: true,
        removeEmptyAttributes: true,
        removeScriptTypeAttributes: true,
        removeStyleLinkTypeAttributes: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
        ignoreCustomFragments: [/\{\{[\s\S]*?\}\}/],
      })
    )
    .pipe(gulp.dest("./public"));
});

// 压缩js文件
gulp.task("minify-js", function () {
  return gulp
    .src(["./public/**/*.js", "!./public/js/**/*min.js"])
    .pipe(uglify())
    .pipe(gulp.dest("./public"));
});

// 压缩图片
gulp.task("minify-images", function () {
  return gulp
    .src([
      "./public/**/*.png",
      "./public/**/*.jpg",
      "./public/**/*.gif",
      "./public/**/*.svg",
    ])
    .pipe(
      imagemin([
        imagemin.gifsicle({ interlaced: true }),
        imagemin.mozjpeg({ quality: 75, progressive: true }),
        imagemin.optipng({ optimizationLevel: 5 }),
        imagemin.svgo({
          plugins: [{ removeViewBox: true }, { cleanupIDs: false }],
        }),
      ])
    )
    .pipe(gulp.dest("./public"));
});

gulp.task(
  "default",
  gulp.series(
    gulp.parallel("minify-html", "minify-css", "minify-js", "minify-images")
  )
);

使用方法

在使用 hexo g 生成静态网站后, 运行 gulp 进行压缩

使用 CDN

如果你查看博客的网络请求内容,你会发现在 html 加载之后,还有一堆小文件等待加载,而这些 css\js\图片文件的加载占据了大部分的网页打开时间。

因为 GitHub Pages 的延迟巨大,速度极慢,我们更有必要使用国内的 CDN 对这些资源进行分发。

不想使用国内付费的 CDN 服务,我尝试过使用 CloudFlare 进行加速(实质减速)效果不佳,后来发现了 jsDelivr。

jsDelivr 是一家开源免费 CDN,主要是对 npm 包进行 CDN 分发

绝妙的是它还能对 GitHub 和 Wordpress 进行 CDN 分发

我们可以借助 jsDelivr 的 GitHub 资源分发 服务来对我们博客中的 css\js\小图片进行加速

这是我目前找到的唯一一家在国内有节点并且不需要备案的 CDN 分发服务

这里我就以我使用的主题为例,分享一下我如何使用 jsDelivr 进行 CDN 分发

链接格式

jsDelivr 针对 GitHub 资源有众多 URL 格式

1
2
3
4
5
6
7
https://cdn.jsdelivr.net/gh/user/repo@version/file
https://cdn.jsdelivr.net/gh/jquery/jquery@3.2.1/dist/jquery.min.js
https://cdn.jsdelivr.net/gh/jquery/jquery@3.2/dist/jquery.min.js
https://cdn.jsdelivr.net/gh/jquery/jquery@3/dist/jquery.min.js
https://cdn.jsdelivr.net/gh/jquery/jquery/dist/jquery.min.js
https://cdn.jsdelivr.net/gh/jquery/jquery@3.2.1/src/core.min.js
https://cdn.jsdelivr.net/gh/jquery/jquery/

考虑到 jsDelivr 默认缓存时间是 7 天,如果我们想要修改实时生效而不需要等到缓存过期,最适合的是

1
2
3
https://cdn.jsdelivr.net/gh/jquery/jquery@3.2.1/dist/jquery.min.js

https://cdn.jsdelivr.net/gh/ github用户名 / 库名 @ 版本号或者tag / 路径/文件名

我们可以通过打 tag 来访问同一个资源文件的不同版本,而不需要考虑缓存时间

替换链接

大部分 hexo 主题并不会对使用到的 js\css\图片\字体 套上 CDN,我们来手动替换

css 样式表

大部分 css 样式会在 head 标签里面引入,这里的 css 样式表会阻塞页面的渲染,导致打开慢的体验,所以需要特别注意

我将我使用的主题的 style.css \ rtl.css \ disquesjs.css 替换成 jsDelivr,明显提升了等待时间

/posts/coding/speedup-github-page/head_huda3a611fef04e94998c80128d5498932_41474_856x388_resize_q75_h2_box.webp

还有一些其他地方的 css 引入

/posts/coding/speedup-github-page/css2_hu68782f409f41f41337cab4c160668330_19406_903x137_resize_q75_h2_box.webp

js 脚本

寻找并替换各种调用到的 js 脚本

/posts/coding/speedup-github-page/js1_hu3c3cc72f09a05a553832e5c2106ee980_35532_1064x241_resize_q75_h2_box.webp

main.js

/posts/coding/speedup-github-page/js2_huc8248fa0d769270c438275256b4c01ee_11115_926x81_resize_q75_h2_box.webp

disqusjs.js

/posts/coding/speedup-github-page/js3_hue3b4a34d93726da7ebc561dbe3f465a5_15629_1003x98_resize_q75_h2_box.webp

还有其他的一些地方,不一一列举了

字体

字体需要特别注意,通常情况下比较大,耗时比较长

/posts/coding/speedup-github-page/font1_hua1f943f9d9ed6f4fc24165b7515c18b7_16884_219x428_resize_q75_h2_box.webp

我使用的主题使用的字体通过 all.min.css 引入,因为前面这个 css 样式已经通过 jsDelivr 导入,里面的字体使用的是相对链接,所以字体默认也是通过 jsDelivr 引入了

img 小图片

一般是 logo 等资源,根据主题自行替换

更新:为了更好的控制版本和决定是否使用 jsDelivr, 可以将这个地方独立出来放到配置文件里

_config.yml

1
2
3
cdn:
  enabled: true
  url: https://cdn.jsdelivr.net/gh/zu1k/blog@0.0.1.2

用到的地方

1
2
3
4
5
6
7
8
<!-- styles -->
<% if (theme.cdn.enabled) { %>
  <link rel="stylesheet" href="<%= theme.cdn.url %>/css/style.css">
<% } else { %>
  <%- css('css/style') %>
<% } %>

其他的地方同样的方法

加载时文字可见

无论怎样优化,字体加载的时间无法忽略,这段时间的网页文字显示为空,这给用户带来卡顿感

我们必须使字体加载时文字可见,这样才能弥补 github pages 的慢

具体方法是将各 @font-facefont-display 设置为 swap, 这样可以在字体未加载完时临时使用系统字体替代,加载完后重新渲染字体

/posts/coding/speedup-github-page/font-swap_hu75f569e462757ed26111cf3470ce8d7f_12458_793x143_resize_q75_h2_box.webp

每一个地方都需要改,自己搜索吧

使用 DisqusJS

由于众所周知的原因,disqus 被墙了,国内访问不了,而大部分 hexo 网站都使用 disqus 作为评论系统,这导致网页会卡在评论区的加载上,虽然网页已经加载完了,但进度条还在进行,给用户带来慢的感觉。

并且,即使有的用户翻墙能够访问 Disqus,但 Disqus 本身非常笨重,各种 CSS/JS/Font/API 加起来请求不小于 2MB,当 Disqus 加载时,浏览器会在主线程中同步解析、渲染 Disqus,造成卡顿感。

在上网搜索之后,找到了一个替代方案,那就是苏卡卡大佬的 DisqusJS,大家可以根据教程对自己博客的主题进行修改

参考链接:

对于使用的 Disqus API 反代,我自己测试发现苏卡卡大佬提供的速度不太行,不知道是什么原因,所以推荐自己进行搭建,我是用的是 zeit 进行搭建,感觉还不错

如果 disqusJS 默认样式不适合自己的主题,推荐 fork 原库进行修改,注意要使用 1.2.6,最新的 master 在懒加载上有点问题

使用懒加载

如果图片和评论区随着页面在一开始就加载,势必会拖累网页首次渲染和文字的迅速显示,这里最好的办法是使用懒加载技术

图片懒加载

对于图片,我使用了 hexo-lazyload-image 这个插件

安装

1
npm install hexo-lazyload-image --save

配置文件中添加

1
2
3
4
lazyload:
  enable: true
  onlypost: false
  loadingImg: https://cdn.jsdelivr.net/gh/zu1k/blog@0.0.1.2/images/loading.png

顺便给懒加载添加了 cdn 功能,可以替换成 cdn 链接来加速

1
npm install hexo-lazyload-image-cdn --save

配置文件中添加

1
2
3
4
5
6
7
lazyload:
  enable: true
  onlypost: false
  loadingImg: # eg ./images/loading.gif
  cdn:
    enabled: false
    url: https://cdn.com

评论懒加载

对于评论区,很多情况下用户根本不会划到页面底部(文章写得太烂没人看得下去)。

所以我这里对 disqus 的加载使用懒加载技术,参考 https://blog.skk.moe/post/prevent-disqus-from-slowing-your-site/

我使用的是 disqusJS, 下面给出加载的 js 代码

 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
30
31
32
33
34
35
36
<!-- DisqusJS Comments -->
<% if (theme.disqusjs.enabled && theme.disqusjs.shortname){ %>
  <script crossorigin defer src="https://cdn.jsdelivr.net/gh/zu1k/DisqusJS@1.2.6.3/dist/disqus.js" id="disqusjs-script"></script>
  <script>
    document.getElementById("disqusjs-script").addEventListener("load",function() {
      setTimeout(
        function() {
          function t() {
            var dsqjs = new DisqusJS({
                  shortname: '<%= theme.disqusjs.shortname %>',
                  siteName: '<%= theme.disqusjs.siteName %>',
                  api: '<%= theme.disqusjs.api %>',
                  apikey: '<%= theme.disqusjs.apikey %>',
                  admin: '<%= theme.disqusjs.admin %>',
                  adminLabel: '<%= theme.disqusjs.adminLabel %>'
              });
          }
          var runningOnBrowser = typeof window !== "undefined";
          var isBot = runningOnBrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro|msn)bot|crawl|spider|yand|duckgo/i.test(navigator.userAgent);
          var supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window;
          if (!isBot && supportsIntersectionObserver) {
              var disqus_observer = new IntersectionObserver(function(entries) {
                if (entries[0].isIntersecting) {
                  t();
                  disqus_observer.disconnect();
                }
              }, { threshold: [0] });
              disqus_observer.observe(document.getElementById('disqus_thread'));
          } else {
            t();
          }
      }, 1);
    },!0
  );
  </script>
<% } %>

终极大招

如果经过上面的优化,你还对博客的加载速度不满意,那一定是 github pages 服务器在美国的原因,200+ms 的延迟导致首字节返回时间不短

其实支持通过 GitHub 仓库代码进行构建,部署为静态网站的平台不值 github pages 一家,我使用过的比较好的是 zeit.co , 国内访问走的是台湾的 gcp 节点,延迟低速度快,推荐

具体使用方法非常简单,自行摸索吧

更新: 刚知道,如果更新太快的话,zeit 会暂停构建部署的

You are pushing commits at a very fast pace (across the whole organization).
Due to that, we cannot deploy the commit e80751b.

You can try again later or upgrade your plan.

辅助优化

使用谷歌提供的 Pagespeed Insights 工具分析网页加载并根据建议进行优化