CDN配置更新

操作步骤

当前阿里云配置的CDN信息如下

CDN概览

主要修正了源站类型,之前设置的源站类型为IP,网站地址为GitHub官方使用的GitHub Pages地址,但是使用IP作为源站其实是不合理的;合理的方法应该是访问我的网站时,流量先经过阿里云 CDN,然后再回源到 GitHub Pages,从而实现加速。仅需要设置www.liuhengfeng.xyz的CDN加速即可,无需单独设置liuhengfeng.xyz的CDN加速!!

源站信息中填写自己的 GitHub Pages 站点地址,优先级选择,GitHub Pages 仅支持 HTTPS,所以你可以填写 443 端口,默认回源HOST地址选择默认的www.liuhengfeng.xyz,并把性能优化的选项都打开

1
2819685584.github.io

源站类型

性能优化

最后在DNS解析控制台设置CDN给出的CNAME即可,这里设置liuhengfeng.xyz的cname指向www.liuhengfeng.xyz,二者使用同样的CNAME来实现加速,但是在浏览器单独输入https://liuhengfeng.xyz/会无法打开网页,也不知道为啥

配置CNAME

无法打开网页

验证

通过cmdnslookup命令查看配置是否成功,出现阿里云提供的cname就成功了,后缀为*.w.kunlunap.com

配置成功

总结

让阿里云 CDN 代理 GitHub Pages 官方域名,然后自定义域名解析到 CDN,就能实现加速

对比

对比

SSL证书更新

在阿里云的数字证书管理服务服务申请证书,然后配置到CDNOSS服务上即可,操作简单,但是证书有效期只有三个月,要在证书过期之前换上新的证书,每年有20张免费的证书可以领,只有两个域名statics.liuhengfeng.xyzwww.liuhengfeng.xyz需要用到证书,够用了

证书

侧边栏电子钟BUG修正

之前每次打开网站都要加载好久,我还以为是加载代码的问题,其实是侧边栏电子钟的API问题,电子钟代码调用了api来获取天气和位置信息,但是和风天气更换了接口的URL地址,导致每次加载电子钟请求数据时都无法获取到数据,一直在等待请求直到401,这个等待的过程时间很长,会显示一直加载,所以就显得网页打开得慢

1
2
3
4
# 旧API地址
https://widget.qweather.net/simple/static/js/he-simple-common.js?v=2.0
# 新API地址
https://devapi.qweather.com/v7/weather/now

通过直接在js里面写死API接口地址来解决这个问题,之前是调用作者提供的网络js文件来加载的,虽然它在js文件中换上了新的接口地址,但还是会出现加载缓慢的问题,这次直接把接口地址写死在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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/**
* 更新时钟和天气显示(保持原有逻辑不变)
* @param {Object} e - 天气数据对象,包含 now 属性(icon、text、temp、humidity、windDir 等字段)
* @param {string} c - 城市名称
*/
function clockUpdateTime(e, c) {
let a = "#000";
switch (e.now.icon) {
case "100":
a = "#fdcc45";
break;
case "101":
a = "#fe6976";
break;
case "102":
case "103":
a = "#fe7f5b";
break;
case "104":
case "150":
case "151":
case "152":
case "153":
case "154":
case "800":
case "801":
case "802":
case "803":
case "804":
case "805":
case "806":
case "807":
a = "#2152d1";
break;
case "300":
case "301":
case "305":
case "306":
case "307":
case "308":
case "309":
case "310":
case "311":
case "312":
case "313":
case "314":
case "315":
case "316":
case "317":
case "318":
case "350":
case "351":
case "399":
a = "#49b1f5";
break;
case "302":
case "303":
case "304":
a = "#fdcc46";
break;
case "400":
case "401":
case "402":
case "403":
case "404":
case "405":
case "406":
case "407":
case "408":
case "409":
case "410":
case "456":
case "457":
case "499":
a = "#a3c2dc";
break;
case "500":
case "501":
case "502":
case "503":
case "504":
case "507":
case "508":
case "509":
case "510":
case "511":
case "512":
case "513":
case "514":
case "515":
a = "#97acba";
break;
case "900":
case "999":
a = "red";
break;
case "901":
a = "#179fff";
break;
}
var t = document.getElementById("hexo_electric_clock");
var clock_box_html = `
<div class="clock-row">
<span id="card-clock-clockdate" class="card-clock-clockdate"></span>
<span class="card-clock-weather">
<i class="qi-${e.now.icon}-fill" style="color: ${a}"></i> ${e.now.text} <span>${e.now.temp}</span> ℃
</span>
<span class="card-clock-humidity">💧 ${e.now.humidity}%</span>
</div>
<div class="clock-row">
<span id="card-clock-time" class="card-clock-time"></span>
</div>
<div class="clock-row">
<span class="card-clock-windDir"> <i class="qi-gale"></i> ${e.now.windDir}</span>
<span class="card-clock-location">${c}</span>
<span id="card-clock-dackorlight" class="card-clock-dackorlight"></span>
</div>
`;
var s = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
var n = document.getElementById("card-clock-loading");

// 定时更新时钟时间、日期和 AM/PM 信息
function r() {
var e,
c = new Date();
var a =
o(c.getHours(), 2) +
":" +
o(c.getMinutes(), 2) +
":" +
o(c.getSeconds(), 2);
var t =
o(c.getFullYear(), 4) +
"-" +
o(c.getMonth() + 1, 2) +
"-" +
o(c.getDate(), 2) +
" " +
s[c.getDay()];
var n = c.getHours();
if (n > 12) {
n -= 12;
e = " P M";
} else {
e = " A M";
}
if (document.getElementById("card-clock-time")) {
var r = document.getElementById("card-clock-time"),
l = document.getElementById("card-clock-clockdate"),
i = document.getElementById("card-clock-dackorlight");
r.innerHTML = a;
l.innerHTML = t;
i.innerHTML = e;
}
}
function o(e, c) {
var a = "";
for (var t = 0; t < c; t++) a += "0";
return (a + e).slice(-c);
}
if (n) {
n.innerHTML = "";
}
t.innerHTML = clock_box_html;
setInterval(r, 1000);
r();
}

/**
* 获取地理位置信息后拼接参数请求天气数据
*/
function getIpInfo() {
let cityName = "长沙市";
let location = "";

// 封装天气请求,确保 URL 始终带上 location 与 key 参数
function fetchWeather(location) {
let weatherUrl = `https://devapi.qweather.com/v7/weather/now?location=${location}&key=${qweather_key}`;
console.log("Fetching weather from: " + weatherUrl);

fetch(weatherUrl)
.then((response) => {
if (!response.ok) {
// 处理 HTTP 错误状态
return response.json().then((errData) => {
throw new Error(
`HTTP ${response.status}: ${errData.code} - ${errData.message}`
);
});
}
return response.json();
})
.then((data) => {
if (document.getElementById("hexo_electric_clock")) {
clockUpdateTime(data, cityName);
}
})
.catch((err) => {
console.error("❌ 天气请求失败:", err.message);
if (err.message.includes("401")) {
console.warn(
"⚠️ 可能的原因: API Key 无效/过期,请检查 QWeather 开发者平台"
);
}
});
}


if (clock_default_rectangle_enable === "true") {
// 使用预设的 rectangle 坐标
location = clock_rectangle;
fetch(
`https://restapi.amap.com/v3/geocode/regeo?key=${gaud_map_key}&location=${clock_rectangle}`
)
.then((response) => response.json())
.then((data) => {
if (data.status === "1") {
const addr = data.regeocode.addressComponent;
cityName = Array.isArray(addr.city) ? addr.province : addr.city;
}
fetchWeather(location);
})
.catch((err) => {
console.error("Error fetching geocode:", err);
fetchWeather(location);
});
} else {
// 使用 IP 定位获取位置
fetch(`https://restapi.amap.com/v3/ip?key=${gaud_map_key}`)
.then((response) => response.json())
.then((data) => {
if (data.rectangle) {
// 如果 rectangle 存在,则使用其第一个坐标
location = Array.isArray(data.rectangle)
? clock_rectangle
: data.rectangle.split(";")[0];
} else {
location = clock_rectangle; // 备用坐标
}
// 如果可以通过逆地理编码获取详细地址,则获取城市名称
if (data.rectangle && !Array.isArray(data.rectangle)) {
fetch(
`https://restapi.amap.com/v3/geocode/regeo?key=${gaud_map_key}&location=${clock_rectangle}`
)
.then((response) => response.json())
.then((addrData) => {
if (addrData.status === "1") {
const addr = addrData.regeocode.addressComponent;
cityName = Array.isArray(addr.city) ? addr.province : addr.city;
}
fetchWeather(location);
})
.catch((err) => {
console.error("Error fetching geocode:", err);
fetchWeather(location);
});
} else {
fetchWeather(location);
}
})
.catch((err) => {
console.error("Error fetching IP info:", err);
fetchWeather(clock_rectangle);
});
}
}

getIpInfo();

更新js文件之后,_config.butterfly.yml配置文件也要修改了,主要修改是把clock_js文件换成本地创建的/js/electric_clock.js,不再调用作者提供的网络js文件;同时,以为已经把接口URL写死在js文件中,因此也不需要 ip_api: https://devapi.qweather.com/v7/weather/now这个选项了,直接注释掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# electric_clock
# see https://blog.anheyu.com/posts/fc18.html
electric_clock:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: all # 应用页面
exclude:
# - /posts/
# - /about/
layout: # 挂载容器类型
type: class
name: card-widget card-announcement # sticky_layout
index: 2
loading: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/loading.gif #加载动画自定义
clock_css: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/clock.min.css
clock_js: /js/electric_clock.js
# ip_api: https://widget.qweather.net/simple/static/js/he-simple-common.js?v=2.0
# ip_api: https://devapi.qweather.com/v7/weather/now
qweather_key: f89c5a6b949a4345a0d22f0ad5b040ea # 和风天气key
gaud_map_key: a36227a8c2b6dcd6b90a98920a06ac89 # 高得地图web服务key
default_rectangle: false # 开启后将一直显示rectangle位置的天气,否则将获取访问者的地理位置与天气
rectangle: 108.230574,22.793414 # 获取访问者位置失败时会显示该位置的天气,同时该位置为开启default_rectangle后的位置

修正之后网页加载速度快了很多,但还是有一个调用天气相关的报错,不知道是在哪些代码调用的,但是相比以前,网页加载速度已经加快了很多了;在这之前我没有注释配置文件的ip_api: https://devapi.qweather.com/v7/weather/now,则会出现另一个请求https://devapi.qweather.com/v7/weather/now的js报错,注释之后则出现新的报错如下,不管了,反正已经算优化过了,影响不大。

错误

总结

可以将需要用到的js或者css文件保存到本地或者oss上,从而保障如果作者下架了文件,不会影响到我的网站,不仅可以做进一步压缩节省空间,还能大幅度节省网页缓冲时间,毕竟OSS的KB级文件响应时间都以ms为单位,基本不会出现缓存20s的情况。不过用到的文件很多,做起来还是挺麻烦的。

后续迁移了一些css/js文件到OSS上,如果以后要修改css/js文件,不能直接在项目里修改代码了,而是本地修改完之后传一份到云端OSS上,因为项目引用的都是网络文件,而不是本地文件了,所有需要上传更新后的文件到OSS上再更新才能显现在web上