原理

在神州大地上,因为众所周知的原因,github访问的速度很慢,甚至有时候会完全中断,让我们没法愉快的利用github提供的优质仓储。好在有了jsdelivr,免费为github所有的公开仓库做CDN,连国内都可以极速访问!使用 jsDelivr 为 Hexo 博客提供高效免费的CDN加速,节省服务器流量且减少宽带占用。不过jsdelivr还有个小小的问题,就是不能及时刷新缓存,github仓库更新后,缓存会在24小时内刷新。一般的CDN会提供强制刷新/回源(purge)机制,然而为了防止滥用,jsdelivr并没有开放此API,据说需要写邮件给jsdelivr说明原因才能开通,让一众白嫖怪们不禁抚掌兴叹。还好,还有个窗户可以爬,可以达到类似强制刷新的效果,就是github仓库更新后,创建一个新的release,然后用https://cdn.jsdelivr.net/gh/user/repo@tag/path/to/resource的方法请求资源,其中tag就是release的名字。

http://ping.chinaz.com/cdn.jsdelivr.net

感受下jsdelivr的加速效果

使用 jsdelivr 加速 Github 仓库资源背景等图

当我们使用 Github 仓库资源时,会因为一些奇怪的原因而掉链子,但我们可以通过 jsdelivr 做 CDN 加速

jsdelivr 是一个免费的开源 CDN

使用方式:

https://cdn.jsdelivr.net/gh/ Github 用户名/仓库名/资源路径

默认会访问 master 分支下的资源,可以通过 仓库名拼接 @ + release / commit / branch 来访问特定版本下的资源

例子:

https://raw.githubusercontent.com/weilining/blog.io/master/images/background-dark.jpg

https://cdn.jsdelivr.net/gh/weilining/blog.io/images/background-dark.jpg

背景图

GitHub仓库:https://github.com/weilining/blog.io/blob/master/images/background-dark.jpg

对应jsdelivr地址:https://cdn.jsdelivr.net/gh/weilining/blog.io/images/background-dark.jpg

修改地址:blog/source/_data/styles.styl

本地

1
2
3
body{
background:url(/images/background-dark.jpg);
}

套jsdelivr作为CDN

1
2
3
body{
background:url('https://cdn.jsdelivr.net/gh/weilining/blog.io/images/background-dark.jpg');
}

头像

GitHub地址:https://github.com/weilining/blog.io/blob/master/images/logo.svg

jsdelivr地址:https://cdn.jsdelivr.net/gh/weilining/blog.io/images/logo.svg

修改地址:_config.next.yml

本地

1
2
avatar:
url: /images/logo.svg

套jsdelivr作为CDN

1
2
avatar:
url: https://cdn.jsdelivr.net/gh/weilining/blog.io/images/logo.svg

鼠标点击特效:社会主义价值观

GitHub地址:https://github.com/weilining/blog.io/blob/master/js/cursor/click-word.js

jsdelivr地址:https://cdn.jsdelivr.net/gh/weilining/blog.io/js/cursor/click-word.js

本地

source/_data/head.njk

1
2
3
<!-- jquery -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="/js/cursor/click-loveword.js"></script>

套jsdelivr作为CDN

1
2
3
<!-- jquery -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/weilining/blog.io/js/cursor/click-loveword.js"></script>

click-loveword.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
74
75
76
77
78
79
80
/* 社会主体核心价值观效果 */
var a_idx = 0;
jQuery(document).ready(function($) {
$("body").click(function(e) {
// var a = new Array("❤富强❤","❤民主❤","❤文明❤","❤和谐❤","❤自由❤","❤平等❤","❤公正❤","❤法治❤","❤爱国❤","❤敬业❤","❤诚信❤","❤友善❤");
var a = new Array("富强","民主","文明","和谐","自由","平等","公正","法治","爱国","敬业","诚信","友善");
var $i = $("<span></span>").text(a[a_idx]);
a_idx = (a_idx + 1) % a.length;
var x = e.pageX,
y = e.pageY;
$i.css({
"z-index": 999999999999999999999999999999999999999999999999999999999999999999999,
"top": y - 20,
"left": x,
"position": "absolute",
"font-weight": "bold",
"color": "rgb("+~~(255*Math.random())+","+~~(255*Math.random())+","+~~(255*Math.random())+")"
});
$("body").append($i);
$i.animate({
"top": y - 180,
"opacity": 0
},
1500,
function() {
$i.remove();
});
});
});
/* 爱心特效 */
! function (e, t, a) {
function n() {
c(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"), o(), r()
}

function r() {
for (var e = 0; e < d.length; e++) d[e].alpha <= 0 ? (t.body.removeChild(d[e].el), d.splice(e, 1)) : (d[e].y--, d[e].scale += .004, d[e].alpha -= .013, d[e].el.style.cssText = "left:" + d[e].x + "px;top:" + d[e].y + "px;opacity:" + d[e].alpha + ";transform:scale(" + d[e].scale + "," + d[e].scale + ") rotate(45deg);background:" + d[e].color + ";z-index:99999");
requestAnimationFrame(r)
}

function o() {
var t = "function" == typeof e.onclick && e.onclick;
e.onclick = function (e) {
t && t(), i(e)
}
}

function i(e) {
var a = t.createElement("div");
a.className = "heart", d.push({
el: a,
x: e.clientX - 5,
y: e.clientY - 5,
scale: 1,
alpha: 1,
color: s()
}), t.body.appendChild(a)
}

function c(e) {
var a = t.createElement("style");
a.type = "text/css";
try {
a.appendChild(t.createTextNode(e))
} catch (t) {
a.styleSheet.cssText = e
}
t.getElementsByTagName("head")[0].appendChild(a)
}

function s() {
return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")"
}
var d = [];
e.requestAnimationFrame = function () {
return e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (e) {
setTimeout(e, 1e3 / 60)
}
}(), n()
}(window, document);

无延迟

jsdelivr github 延迟,建议使用https://cdn.jsdelivr.net/gh/ Github 用户名/仓库名/@tag/资源路径

1.有延迟:https://cdn.jsdelivr.net/gh/weilining/blog.io@master/js/cursor/

2.有延迟:https://cdn.jsdelivr.net/gh/weilining/blog.io/js/cursor/

3.有延迟:https://cdn.jsdelivr.net/gh/weilining/blog.io@latest/js/cursor/

4.无延迟:https://cdn.jsdelivr.net/gh/weilining/blog.io@1.0/js/cursor/

5.无延迟:cdn改成purge,访问一下这个链接来刷新原来的缓存

https://purge.jsdelivr.net/gh/weilining/blog.io/js/cursor/

再打开https://cdn.jsdelivr.net/gh/weilining/blog.io/js/cursor/

其中,2和3等价

你输入https://cdn.jsdelivr.net/gh/weilining

提示:Invalid URL. The URL structure is /gh/user/repo@version/file.js

也就是说jsdelivr其实本身就是加速js的

GitHub CDN

根据 jsdelivr 说明,要使用 GitHub CDN,需要仓库设为公开,且打上 git tag 版本号。小提示,jsdelivr 支持不带版本号的 url,但发布到线上的页面一定要带版本号,不然很可能因为缓存问题使用的不是最新的资源。

优化 JavaScript 和 CSS

尽量减少 JavaScript/CSS 体积,因为这类文件大小除了影响网络加载,大体积意味着更多的代码,浏览器需要花更多时间去解析 + 执行代码。

常规的压缩,uglify 就不用讲了。还可以通过 webpack-bundle-analyzer 分析 JS 模块大小,揪出最影响 js 体积的包,想办法优化。比如:通过分析发现 mdx live 实时编辑预览功能相关 lib 体积巨大,而本博客目前尚无此需求,去掉相关依赖之后包体积减少了 600+ kb,效果显著。

实在不能去掉的 JS 包还可以把大包拆成小包,首屏只阻塞(同步)加载最关键的 JS 和 CSS(比如内联),剩余的 JS 可以使用 html prefetch/preload 延迟(异步)加载。这类功能 gatsby 内置的,开发者基本无感。

别忘了开启 gzip 压缩HTTP 缓存,进一步减少下载量,HTTP 缓存策略也适用于图片等外联资源。

减少资源数量和大小

CDN 帮助提高网络下载速度,但从源头本身还能做很多文章,减少不必要的资源数量和大小!哪怕资源体积很小,浏览器也要解析 DNS,建立 HTTP 链接,下载资源,占用宝贵的加载时间。

减少图片大小

网站一般使用很多图片来提升用户体验,减少图片大小能有效提升网站加载性能。年轻的我曾使用 https://unsplash.com 未经压缩的 4k 原图作为文章封面,单个图片最高达到恐怖的 7mb,使用体验可想而知 😂。

页面使用的图片一定要先压缩,在线压缩工具可选 https://tinypng.com:用户体验好,但有 5m 大小限制;http://jpeg-optimizer.com: 没有体积大小限制,还能调整图片像素大小。

注意某些有损压缩算法会把图片透明背景去掉,导致显示效果大打折扣。gatsby 这类框架还支持自动生成 webp(Google 推出的开源图片格式,相比 png、jpg, 同等质量下体积更小,但不是所有浏览器都支持,参考 caniuse),进一步降低图片体积。gatsby 支持构建多份图片以适配浏览器最佳图片格式,但注意 jsdelivr 在体积超过 50m 之后会有限制,酌情使用。

去掉字体,内联 svg

去掉第三方字体,使用系统默认的字体,相关系统自带字体推荐请看另一篇博文 Web 开发中文字体指南

使用 react 等技术栈可以直接把 svg 放在组件渲染,减少不必要的外链。参考代码: Copy.Icon.tsx。很多 svg 图标也可以换成 iconfont,减少体积和请求数量。