Vercel加速

使用Vercel加速GitHub Pages

https://xiaoliblog.cn/page/vercel.html

JsDeliver加速文件

前期准备

  • 一个GitHub账号
  • 创建一个仓库用于上传文件
  • 上传文件或者图片后就可以通过JsDeliver链接方式加速

已搭建好博客仓库的可以忽略

JSD链接

  • 比如我想访问博客仓库img目录下的404.jpg
  • 可以通过JSD链接访问https://cdn.jsdelivr.net/gh/xiaoliblog/xiaoliblog.github.io/img/404.jpg
  • 格式:https://cdn.jsdelivr.net/gh/<用户名>/<仓库名>/<文件及路径>
  • 比如以上链接:https://cdn.jsdelivr.net/gh/xiaoliblog/xiaoliblog.github.io/img/404.jpg代表GitHub用户名xiaoliblog下的xiaoliblog.github.ioimg目录下的404.jpg
  • 分支与版本号加到仓库后面,用 @符链接。格式为:https://cdn.jsdelivr.net/gh/<用户名>/<仓库名>@[分支/版本号]/<文件及路径>
分支名 简述 特点
普通分支 即 GitHub 的分支,可以创建多个。默认为 master 按分支引用,如同按分支开发
latest 最后一次提交 代表最后一次的提交,即每上传一个新文件,都可以用这个分支引用到。也就是不加版本号的默认情况。
版本号 即指定版本的内容,需配合版本发布 已发布的版本不会受到仓库内容变化的影响
  • 使用版本号引用的优点在于:这个链接仅停留在发布版本号的时刻,无论仓库如何变化,这个版本号的文件都不会受到影响。同时可以避免 JSD 缓存问题
  1. 发布版本
  2. 使用版本号访问image仓库下的headimg.jpg
    访问链接:https://cdn.jsdelivr.net/gh/xiaoliblog/image@v1.0/headimg.jpg,可以发现只在仓库名image后面加上@版本号即可

静态资源加速

图片资源加速

  • 压缩图片分为有损压缩和无损压缩。无损压缩推荐 Tinypng,有损压缩推荐 imagine
TinyPNG Imagine
特点 无损压缩 有损压缩,以牺牲图像质量,降低图像色彩来达到缩减图像大小的目的。
优点 能够完全保留图像色彩,不损伤图像质量 1. 压缩程度高,支持转 png 为 jpg 或 webp,进一步减少图片大小2. 软件支持一次处理多张图片,无上限,处理完成支持直接批量覆盖原文件或重命名
缺点 单次仅能上传 20 张图片,每张限制大小为 5MB,无法处理更大图片。 PNG 转其他格式为不可逆操作(指覆盖保存后),且可能反而会增加图片大小。

如果没有特别要求,直接使用Imagine进行有损压缩即可。虽然说是有损压缩,但是默认压缩会自主计算压缩程度,一般默认程度就能节省 70% 空间,且肉眼几乎发现不了图片压缩情况。

Gulp 压缩全站静态资源

1
2
npm install -g gulp-cli 
npm install gulp --save-dev
  • 安装压缩 HTML
1
2
npm install gulp-htmlclean --save-dev
npm install gulp-html-minifier-terser --save-dev

压缩HTML gulp-html-minifier-terser 可以压缩 HTML 里的 ES6 语法

  • 安装压缩CSS
1
npm install gulp-clean-css --save-dev
  • 安装压缩JS
1
2
npm install --save-dev gulp-uglify
npm install --save-dev gulp-babel @babel/core @babel/preset-env
  • 在博客根目录下创建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
var gulp = require('gulp');
var cleanCSS = require('gulp-clean-css');
var htmlmin = require('gulp-html-minifier-terser');
var htmlclean = require('gulp-htmlclean');

var uglify = require('gulp-uglify')
var babel = require('gulp-babel')

gulp.task('compress', () =>
gulp.src(['./public/**/*.js', '!./public/**/*.min.js'])
.pipe(babel({
presets: ['@babel/preset-env']
}))
.pipe(uglify().on('error', function (e) {
console.log(e)
}))
.pipe(gulp.dest('./public'))
)

gulp.task('minify-css', () => {
return gulp.src(['./public/**/*.css'])
.pipe(cleanCSS({
compatibility: 'ie11'
}))
.pipe(gulp.dest('./public'));
});

gulp.task('minify-html', () => {
return gulp.src('./public/**/*.html')
.pipe(htmlclean())
.pipe(htmlmin({
removeComments: true, //清除 HTML 註释
collapseWhitespace: true, //压缩 HTML
collapseBooleanAttributes: true, //省略布尔属性的值 <input checked="true"/> ==> <input />
removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input />
removeScriptTypeAttributes: true, //删除 <script> 的 type="text/javascript"
removeStyleLinkTypeAttributes: true, //删除 <style> 和 <link> 的 type="text/css"
minifyJS: true, //压缩页面 JS
minifyCSS: true, //压缩页面 CSS
minifyURLs: true
}))
.pipe(gulp.dest('./public'))
});

// 执行 gulp 命令时执行的任务
gulp.task('default', gulp.parallel(
'compress', 'minify-css', 'minify-html'
))
  • hexo g之后运行gulp进行压缩
1
hexo cl && hexo g && gulp

异步加载

详情请参考Akilar大佬的Hexo 异步加载方案:https://akilar.top/posts/615d5ede/

  • 当我们的博客引入大量的第三方脚本(js),而基于页面读取 js 的加载顺序,每当浏览器在加载 html 的过程中遇到 <script>js代码片段</script> 这样的标签时,浏览器会暂停继续构建 html,而是优先执行当前的 js 脚本,等执行完毕后再继续加载后面的 html
  • 至于外部脚本 <script src="js外链"></script> 这样的写法,更是要先下载脚本,然后再执行,之后才能继续处理剩余的页面
  • 无形中,多出了一大把的加载时间。我们可以通过给 <script></script> 添加 deferansyc 属性来实现异步加载,调整 js 的加载时间和顺序,确保浏览器构建 HTML 的过程一切顺利

原理剖析

此图来源于Akliar大佬的异步加载方案原理https://akilar.top/posts/615d5ede/

  • 可以看到,总的 HTML 加载时间,下载脚本的时间,执行脚本的时间是固定的。不同之处在于 HTML 阻塞的时间以及执行脚本的次序
  • 不加任何 async 和 defer 的情况,页面总加载时间最长,是
    • HTML 加载时间 + 下载脚本时间 + 执行脚本时间
  • 加了 async`和 defer 的时间,在加载 HTML 时间足够长的情况下,所有静态资源总的加载时间都是
    • HTML 加载时间 + 执行脚本时间

使用范例

  • defer 特性除了告诉浏览器不要阻塞页面之外,还可以确保脚本执行的相对顺序。
    • 这个很适合使用到 Vue 和 jquery 等 js 框架的 js 脚本,给它们添加 defer 属性以后,可以确保 HTML 加载完毕,且 js 下载完毕后,各个 js 脚本继续按照引入的顺序执行,从而确保不会因为依赖缺失而报错。
  • 其他脚本不会等待 async 脚本加载完成,同样,async 脚本也不会等待其他脚本。
    • 这个适合使用原生 js, 没有引用任何 js 框架,自己独立就能运行,且体量相对较小的 js 脚本,随页面加载同步下载执行。
  • async 加在那些非必要的,起装饰或者优化效果的 js 上,defer 加在那些确保页面完整性的必要 js 上
  • 不要给影响页面生成的 js(例如 util.jsmain.jslazy_load.jsvue.jsjquery.js)添加异步加载标签 (不论是 async 还是 defer 都不要加),不然会造成大面积页面功能模块失效
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
bottom:
- <script defer https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
# Vue.js作为依赖项,必须确保在所有使用到它提供的方法的诸多js之前引入,并且添加defer
- <script defer src="/live2d-widget/autoload.js"></script>
# 看板娘使用到了jquery依赖,所以需要defer
- <script async src="/js/dytitle.js"></script>
# 动态网页标题是原生js,且体量小,可以直接async
- <script async src="/js/mouse_snow.min.js"></script>
# 鼠标滑动雪花是原生js,且体量小,可以直接async
- <script defer data-pjax src="/clock/js/clock.js"></script>
# 首页电子钟用到了vue依赖,所以需要defer
- <script defer data-pjax src="/magnet/catalogMagnet.js"></script>
# 首页磁贴用到了vue依赖,所以需要defer
- <script defer src="/botui/botui.js"></script>
- <script defer data-pjax src="/botui/botui_init.js"></script>
# 侧栏聊天窗用到了vue依赖,所以需要defer
- <script defer src="/runtime/flipcountdown.js"></script>
- <script defer data-pjax src="/runtime/runtime.js"></script>
# 页脚计时器用到了jquery依赖,所以需要defer
- <script defer src="https://cdn.jsdelivr.net/npm/artitalk"></script>
- <script defer data-pjax src="/artitalk/artitalkkey.js"></script>
- <script defer data-pjax src="/artitalk/artitalk.js"></script>
# 侧栏说说依赖于artitalk.js,必须确保其加载顺序,在保证页面引入顺序的同时添加defer
- <script async src="/js/redirect.js"></script>
- <script async src="/js/mirror.js"></script>
# 404和镜像站重定向都是原生js,可以直接async
- <script defer data-pjax src="https://cdn.jsdelivr.net/gh/Akilarlxh/Akilarlxh.github.io@v3.3.3_3/gitcalendar/js/gitcalendar.js"></script>
# gitcalendar用到了vue依赖,所以需要defer

CSS 异步加载

  • CSS没有JS添加异步那么方便,
  • 一种方法是通过定义一个无效 media,使得该 CSS 引入优先级最低,再用 onload="this.media='all'" 在页面加载完成后纠正 media,并加载 CSS
1
<link rel="stylesheet" href="/example.css" media="defer" onload="this.media='all'">
  • 还有一种利用 `rel=”preload” 属性的方案,但是目前只有 Chrome 浏览器可以完美支持,等推广还需要很长一段时间,写法如下:
1
<link rel="preload" href="cssfile.css" as="style" onload="this.rel='stylesheet'">