惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
C
Cisco Blogs
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Archives - TechRepublic
Security Archives - TechRepublic
TaoSecurity Blog
TaoSecurity Blog
V2EX - 技术
V2EX - 技术
H
Heimdal Security Blog
S
Security Affairs
L
Lohrmann on Cybersecurity
Hacker News - Newest:
Hacker News - Newest: "LLM"
Simon Willison's Weblog
Simon Willison's Weblog
WordPress大学
WordPress大学
小众软件
小众软件
Security Latest
Security Latest
AWS News Blog
AWS News Blog
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
F
Full Disclosure
S
Schneier on Security
L
LangChain Blog
MyScale Blog
MyScale Blog
Know Your Adversary
Know Your Adversary
P
Privacy International News Feed
Google Online Security Blog
Google Online Security Blog
Scott Helme
Scott Helme
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
A
Arctic Wolf
Martin Fowler
Martin Fowler
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
The Register - Security
The Register - Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
Latest news
Latest news
F
Fortinet All Blogs
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
Hacker News: Ask HN
Hacker News: Ask HN

文章列表 - 她和她的猫

使用小鹤双拼一个月 折腾 Hugo PaperMod 主题 去长鹿旅游休博园 1Password 自动化登录堡垒机 深入 Hyperf:Inject 注解是如何工作的? 译|理解容器镜像层 使用 Rust 实现高性能预写日志(Write Ahead Log) 译|使用 Linux 命名空间隔离系统 深入 Hyperf:HTTP 服务是如何处理请求的? Linux 文件权限学习笔记 译|了解 Bitcask:基于日志结构的 KV 存储引擎 还原 SM2 压缩公钥的几种方法 深入 Hyperf:HTTP 服务启动时发生了什么? 一次 Hyperf 注解失效问题分析 译|PHP 7 新的 Hashtable 实现 排查 ES 查询问题:深入了解 json_encode() 函数 浅析 Redlock 分布式锁实现原理 Yar 源码阅读笔记:RPC 服务端 Yar 源码阅读笔记:客户端的并行调用 Yar 源码阅读笔记:客户端的同步调用 Yar 源码阅读笔记:数据传输模块 Yar 源码阅读笔记:消息编码模块 Yar 源码阅读笔记:RPC 通信协议 Yar 源码阅读笔记:开篇 PHP 8 新特性介绍 基于 OpenSSL 实现国密 SM4 加解密 PHP 源码阅读笔记:编译与调试 PHP 什么是惊群问题 大端模式和小端模式 基于 GitHub Actions 定时推送网址到百度站长平台 聊聊五种 I/O 模型 Workerman 源码分析:文件上传 浅入浅出 HTTP 协议 PHP 网络编程:构建 MySQL 蜜罐获取攻击者微信 ID 使用 Workerman 接入 Bilibili 直播弹幕协议 使用 GitHub Actions 自动部署 Hexo 什么是二进制安全 【转载】PHP 程序员进阶之路 优化 Workerman 检查主进程是否存活的逻辑 基于 Redis 实现分布式锁 《PHP 实现 Base64 编码/解码》笔记 PHP 多进程下载必应壁纸 基于 Redis 实现延迟队列 【转载】PHP 实现 Base64 编码/解码 使用 MySQL FIELD() 函数自定义排序规则 Laravel 的 Facades 实现原理 C语言单链表实现约瑟夫环 数据结构学习笔记:顺序栈和链栈(C语言) 使用 QueryList + Redis 下载壁纸 在 Laravel 登录/注册中使用 mews/captcha 扩展包 使用 mews/captcha 扩展包为 Laravel 应用添加图片验证码 给 YOURLS 短网址系统编写插件《批量生成短网址》 给 YOURLS 短网址系统编写插件《Hello World!》 PHP 7.1 使用 json_encode 函数造成浮点类型数据出现精度问题 Laravel 授权策略(Policy)的基本使用 Ubuntu 系统下 WiFi 频繁掉线解决方法 Laravel 应用部署到 Nginx 服务器上的第一个坑 Ubuntu 16.04 LST 安装 Redis 和 Composer PHP 采集逐浪小说章节列表 Nginx 环境 SSL 强制 HTTP 301 跳转到 HTTPS 【工作&生活】第一周 ServiceStack.Redis 与多线程 Count the number of Duplicates C# Base64 加密及解密 ASP.NET MVC 使用动态类型传递数据 Django 使用 order_by() 对数据进行排序操作 ASP.NET + jQuery + AJAX 实现用户登录 ASP.NET 从客户端中检测到有潜在危险的 Request.Form 值 ASP.NET 使用 FormData 实现 AJAX 上传图片 Python 使用 BeautifulSoup 抓取网页 贪心算法之字符串的完美度 一言不和就造轮子之 CookieHelper ASP.NET 上传图片 DBHelper 类 C# 捕获屏幕源码 用 JavaScript 做一些有趣的事情 第一篇文章 好久不见。 如何防止非法调用 PHP 文件 清明小记。 PHP 生成随机字符串 Z-Blog PHP 程序做 301 跳转 PHP 处理数组常用的几个函数 Sublime Text 3 快捷键总结 PHP 使用 file_get_contents() 函数实现采集网页 使用 C# 编写学生信息管理系统 终于到了。 zblog报错: magic_quotes_gpc 和 safe_mode 世事无常。 如何使用 PHP 上传文件 安卓手机编写和运行 PHP 程序的软件 使用 AJAX 刷新、验证 PHP 图片验证码 PHP 生成图片验证码 PHP 之 session 的使用方法 PHP 之 cookie 的使用方法 PHP 实现分页原理详解 Thinkphp 框架中系统常量在 Js 文件中不解析的解决方法
将博客迁移到又拍云
她和她的猫 · 2023-01-31 · via 文章列表 - 她和她的猫

考虑到使用一台独立的服务器来部署静态博客多少有点浪费,所以决定将博客迁移到又拍云上,一是可以节省服务器成本;二是可以利用又拍云多节点 CDN 提升博客的访问速度。之前为了将博客图片托管到又拍云上,参加了又拍云的联盟活动,每个月可以免费获得 10GB 存储空间 + 15GB CDN 流量,对于我这个小博客是完全够用的。

编写部署脚本

首先,为了能够通过 Github Actions 将博客文件自动同步到又拍云上,需要写一个脚本来实现上传文件的逻辑。

在此之前,我已经写过一个这样的脚本,用来将博客图片同步到又拍云上。这次用 Go 重写了这个脚本,旧版本的脚本执行需要四十多秒,而新的脚本执行只需要三秒钟。

主要是因为使用了 Go 语言自带的协程和 Channel,并将上传文件的逻辑放在协程中,使得主流程不会被上传文件的动作阻塞,实现并发上传文件,从而达到提升执行速度的目的。

相关代码已经上传到 GitHub:https://github.com/her-cat/upyun-deployer,感兴趣的话可以看一下。

脚本的逻辑分为两部分:上传文件、清理已删除的文件和空目录。

上传文件

上传文件时,先检查文件在又拍云存储库中是否已经存在,如果不存在则直接上传;存在的话就检查文件的 md5 值是否一致,一致则说明该文件没有被修改,不需要处理该文件,否则重新上传该文件。

清理已删除的文件和目录

当本地删除了某个文件后,又拍云的存储库要同步删除该文件;当目录中没有任何文件时,需要删除该目录。

为了实现这一点,在上传文件之前,我们需要从又拍云拿到所有的文件及目录的相对路径,并保存到 files 和 dirs 数组中。 每次上传本地文件时,先将本地文件的相对路径从 files 数组中删除,并将该路径对应的多级目录从 dirs 数组中删除。

当所有的本地文件都上传完毕后,files 和 dirs 数组中剩余的文件和目录就是我们要清理的内容,直接调用又拍云删除接口即可。

要注意的是,删除目录时,需要从最深层的目录开始删除,否则就会由于目录中存在子目录导致删除失败,即使子目录是空的。

比如有 /a/b/a/a/b/c 三个目录,一定要按照 /a/b/c/a/b/a 的顺序依次删除。

设置边缘规则

将所有文件都上传到又拍云之后,我们就可以直接在浏览器中访问博客了。但是,有时候需要配置一些重定向规则,比如旧文章的 URL 重定向、资源不存在时自动跳转到 404 页面等等。在使用服务器部署的时候,都是通过编写 Nginx 配置来实现这些规则,而在又拍云中则是通过设置「边缘规则」。

边缘规则支持两种设置方式,第一种是通用模式,这种模式上手简单,不需要了解边缘规则的语法规则;第二种是编程模式,比前一种模式更加灵活、强大,前提是你要熟悉它的语法规则。

下面是我配置的一些边缘规则。

统一域名

第一个规则是为了统一域名,我的博客域名是 her-cat.com,而有的人则喜欢使用 www.her-cat.com 进行访问。为了兼容这两种方式,我将 her-cat.com 和 www.her-cat.com 都解析到了又拍云上,然后使用边缘规则对请求的域名进行检测,当域名等于 www.her-cat.com 时,就使用 301 跳转到 her-cat.com。

这个规则我使用的是编程模式,规则内容如下:

$WHEN($EQ($_HOST,www.her-cat.com))$REDIRECT(https://her-cat.com$_URI,301)

语法说明:

  • $_HOST:请求的域名
  • $EQ:判断两个值是否相等,返回 true 和 false
  • $WHEN:条件判断语句,当括号中为 true 时,执行后面的语句
  • $REDIRECT:执行重定向,第一个地址重定向的地址,第二个是状态码

旧文章重定向

在国庆的时候,我将静态博客的构建工具从 hexo 换成了 hugo,带来的问题就是博客中所有文章的地址都发生了变化。原来的地址是 https://her-cat.com/年/月/日/slug.html,新的地址是 https://her-cat.com/posts/年/月/日/slug/。可以看到,域名后面多了 posts 并且删除了 .html 文件后缀,变成了 / 结尾。由于一些文章已经被收录或者其它站点所引用,如果不进行重定向就会导致无法使用原来的地址访问。

这里使用的也是编程模式,与上一个规则相比多了一个步骤,需要先 URL 中提取出年、月、日、slug,然后再进行 301 重定向。

URL 字符串提取:

^/(\d+)/(\d+)/(\d+)/([\w-]+).html$

规则内容:

$REDIRECT(https://her-cat.com/posts/$1/$2/$3/$4/,301)

在 URI 结尾追加 /

在 hugo 中,强制要求所有页面的 URI 都必须以 / 结尾,否则无法找到对应的页面。

解决方法是当检测到 URI 不是以 / 结尾时就自动追加 / 并 301 重定向,当然还有一些特殊情况需要处理,比如请求的是文件时不做处理。

这里使用的是通用模式。

条件判断:

  • 请求 URI 正则不匹配(不区分大小写)^/.*/$
  • 并且 请求 URI 正则不匹配(不区分大小写)(jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|txt|html|xml|js|css|woff2)$
  • 并且 请求 URI 正则不匹配(不区分大小写) /$
  • 并且 请求 URI 不等于 /

满足以上条件时,执行功能:

  • 执行 边缘重定向 动作,响应 301 状态码,重定向地址为 https://her-cat.com$_URI/

404 页面

最后一个规则是当请求的页面不存在时,自动重定向到 404 页面。执行重定向动作之前,需要先判断请求的文件类型,如果是资源文件则不处理,只重定向对页面的请求。

这里使用的是通用模式。

条件判断:

  • 请求 URI 正则不匹配(不区分大小写)(jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|txt|html|xml|js|css|woff2)$

满足以上条件时,执行功能:

  • 执行 自定义错误页面 动作,响应 404 状态码,跳转地址为 https://her-cat.com/404.html

到这里边缘规则就全部设置完了,在使用正则表达式的时候需要注意,边缘规则并不支持标准的正则表达式。

比如匹配以 .html 结尾的 URI 时,正常使用 \.html$ 就可以了,但是又拍云不支持 \. 这种写法,并且没有任何错误提示,需要不断地编辑、保存规则然后进行调试才能找到问题。

其它设置

下面是又拍云提供的一些功能,可以提升博客的体验以及访问速度。

  • 浏览器缓存:启用配置图片、字体、样式等文件的缓存。
  • 智能压缩:开启 Gzip 和 Brotli 压缩,减少传输内容大小。
  • 页面压缩:自动去除页面文件中非必要的字符(空白、注释等),加快传输速度。
  • TLS 1.3 加密协议:一种全新的加密协议,它既能提高终端用户的访问速度,又能增强安全性。
  • HTTP/2 传输协议:支持包括采用二进制格式传输数据、对消息头采用 HPACK 进行压缩传输、多路复用等特性。
  • WebP 自适应:智能判断浏览器是否支持 WebP,来决定返回 WebP 格式图片还是原图,从而减少网络传输消耗。
  • HTTPS:可以使用 Let’s Encrypt 免费的证书,并且支持自动续费。

优化博客访问速度

使用 PageSpeed Insights 工具对博客进行分析后,发现博客有很多可以优化的地方,比如字体文件、图片等资源的加载。下面是优化前后的评分对比。

优化前:

优化后:

优化字体加载

Eureka 主题默认使用 Google fonts 来加载所需的字体文件:

https://fonts.googleapis.com/css2?family=Lora:wght@400;600;700&family=Noto+Serif+SC:wght@400;600;700&display=swap

可以看到,主题使用了两种字体:Lora 和 Noto Serif SC,后面的 400;600;700 表示需要三种粗细值,display=swap 表示在 Google fonts 加载完成之前,先用系统自带的字体完成页面渲染,字体加载完成之后再用相应的字体进行渲染,避免加载字体时白屏闪烁的问题。

下面是该请求返回的 CSS 样式(部分):

/* cyrillic-ext */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/lora/v26/0QIvMX1D_JOuMwf7I_FMl_GW8g.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/lora/v26/0QIvMX1D_JOuMw77I_FMl_GW8g.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

像这样的 @font-face 定义一共有 306 个,也就是说最坏的情况需要发起 306 个请求才能完成页面上所有字体的渲染,为什么要分成这么多字体文件呢?

目的是按需加载字体文件,提高字体的加载速度。在 unicode-range 中定义了字体文件包含的字符编码范围,当页面上需要用到相应的字符时,浏览器就会请求 src 中的地址加载字体文件进行渲染。

分析网络请求后发现,首次打开博客大概需要发起 30 多个请求来获取字体文件,由于 Google fonts 的服务器在国外,所以即使开启了浏览器缓存,首次访问还是需要花费较长的时间。为了解决这个问题,我将字体文件上传到了又拍云,通过又拍云的 CDN 节点提升字体的加载速度。

操作步骤:

  • 将 CSS 文件中所有的字体按照路径下载到本地。
  • 将 CSS 文件中所有的 fonts.gstatic.com 替换成又拍云的访问域名。
  • 将 CSS 文件和字体文件按照路径上传到又拍云。

打开 /fonts/fonts-family.css 可以看到最终效果。

除此之外,还需要在又拍云中为字体文件配置浏览器缓存,避免每次都从又拍云加载字体文件。

优化图片加载

关于图片的优化主要是首页的头像和底部的又拍云 Logo。

头像的问题在于没有给图片设置宽度和高度,如果图片在页面渲染完成之后才加载出来,会导致图片附近的元素会发生位移,会感觉页面好像抖了一下。

又拍云 Logo 问题在于加载的图片很大,但是实际上又不需要这么大的图片,可以使用又拍云的图片处理对图片进行压缩。

优化资源文件加载

在查看分析报告的时候,发现博客中所有的页面都加载了代码高亮和评论模块的 JS 以及 CSS 文件,但实际上除了详情页面以外,其它页面都不需要代码高亮以及评论功能。为了解决这个问题,我们只需要在 baseof.html 页面中判断一下的页面类型,只有详情页面才加载代码高亮和评论模块相关资源。

首先将主题下的 baseof.html 文件拷贝到博客的 layouts/_default/ 目录下,对 baseof.html 文件进行重写,然后将文件中代码高亮和评论相关的代码删除,替换成以下内容:

{{ $currentPage := . }}
{{/* 判断是否为详情页面 */}}
{{ if eq $currentPage.Kind "page" }}
{{/* 引入评论相关资源 */}}
<link rel="stylesheet" href="https://unpkg.com/gitalk@1.8.0/dist/gitalk.css">
<script id="gitalk_js" async src="https://unpkg.com/gitalk@1.8.0/dist/gitalk.min.js"></script>
{{/* 引入代码高亮相关资源 */}}
{{- $assets := .Site.Data.assets }}
{{- if eq .Site.Params.highlight.handler "chroma" }}
{{- $highlightCSS := resources.Get "css/syntax.css" | minify | fingerprint "sha384" }}
<link rel="stylesheet" href="{{ $highlightCSS.Permalink }}" media="print" onload="this.media='all';this.onload=null">
{{- else if eq .Site.Params.highlight.handler "highlightjs" }}
{{- $highlightjsStyle := .Site.Params.highlight.highlightjs.style | default "base16/solarized-light" }}
<link rel="stylesheet" href="{{ printf $assets.highlightjs.css.url $assets.highlightjs.version $highlightjsStyle }}"
      {{ with $assets.highlightjs.css.sri }} integrity="{{ . }}" {{ end }} media="print"
      onload="this.media='all';this.onload=null" crossorigin>
<script defer src="{{ printf $assets.highlightjs.js.url $assets.highlightjs.version }}"
        {{ with $assets.highlightjs.js.sri }} integrity="{{ . }}" {{ end }} crossorigin></script>
{{- range .Site.Params.highlight.highlightjs.languages }}
<script defer src="{{ printf $assets.highlightjs.languages.url $assets.highlightjs.version . }}"
        {{ with $assets.highlightjs.languages.sri }} integrity="{{ . }}" {{ end }} crossorigin></script>
{{- end }}
{{- $highlightjsCSS := resources.Get "css/highlightjs.css" | minify | fingerprint "sha384" }}
<link rel="stylesheet" href="{{ $highlightjsCSS.Permalink }}" media="print" onload="this.media='all';this.onload=null">
{{- end }}
{{ end }}

总结

这篇文章介绍了我是如何将博客迁移到又拍云并实现自动化更新博客的,顺便介绍了如何使用边缘规则来实现对请求的处理,最后提到了我对博客的一些优化,虽然优化的手段都比较常规,但实际效果还是很不错的。

最后,祝大家兔年大吉!