type
status
date
slug
summary
tags
category
icon
password
NotionNext默认使用的是Notion图床。Notion在国内没有服务器,所以通过
Notion.so
域名请求的图片资源文件在国内的访问速度不是很好,我们可以通过使用Caddy反向代理的方式加快Notion.so
的图片访问,降低加载图片所需时间,从而提高使用NotionNext的博客在国内的访问速度与用户体验。我这个使用NotionNext,部署在Vercel上的博客页面加载时间太长的问题,也是由于昨天突然博客的国内用户的访问量增加,我在Cloudlfare Web Analytics里面进行日常数据查看时发现的,涉及到的文章页面主要是《小米15手机(澎湃OS2):如何关闭推荐广告 | Deep Router》这篇文章,原因在于这篇文章我放了很多的手机截屏图片,这些图片需要进行加载,即使我已经使用了图片的延迟加载功能,但是依旧会因为首屏需要加载3-4张图片,而造成整体页面的加载时间过长,影响用户体验。因为Notion在国内没有服务器,访问速度不算很好,所以大部分图片的LCP(Largest Contentful Paint)延迟都在5秒左右,FCP也因为我未使用
webp
格式的图片造成访问延迟上升。在一篇包含很多张图片的文章里,整体的加载速度更堪称灾难级,可能需要30秒以上才能完成首屏加载,这一点在移动端设备上,因为性能差异进一步被放大。为了优化博客国内的访问体验,所以我尝试寻找解决方案,让NotionNext的图片加载不再那么灾难。在《Nginx设置Notion反代加速NotionNext图片资源访问》这篇文章中,作者提到可以通过使用Nginx反向代理(反代)方式进行解决,通过Nginx将用户对图片素材的访问请求反向代理至notion.so
,这样只要部署Nginx的机器在国内的访问速度够快,那么托管的Notion上的图片资源也能够很快的进行加载,降低LCP延迟。我没有使用Nginx作为Web服务器,而是使用的Caddy这个更轻量化的解决方案,所以就在这篇文章的基础上,提供一份基于Caddy的反向代理解决方案。在开始之前,我们先查看一下目前
Notion.so
在国内的访问情况,大部分浅绿,平均加载时间在3s左右,且在部分地区无法直接进行访问:
📝 Caddy反向代理配置前提
你需要一台云服务器,境内境外均可,我所使用的小鸡(云服务器)是在香港,购自CoalCloud(碳云),国内访问速度在ITDOG上查询还不错。平常只作为RSS推送服务和Docker加速镜像使用。如果不使用Cloudflare的话,需要自行在云服务器为用于反向代理的域名申请证书,例如使用letsencrypt或者acme,但是如果你也和我一样使用Caddy的话,那么Caddy会自动帮你通过acme申请好所配置的域名的证书。
也有一些解决方案是通过Cloudflare Worker实现,我没有使用Cloudflare Worker进行反向代理的原因是担心会被认为在滥用,从而导致Cloudflare账号被封禁(Ban)或限制服务。
📝 什么是Caddy
Caddy是一个开源的Web服务器和反向代理工具,专注于简化配置流程和提升安全性。它以自动化HTTPS部署为核心特性,无需手动操作即可为站点申请并更新 SSL/TLS证书。支持HTTP/3、静态文件托管、负载均衡等功能,通过简洁的配置文件(或直接通过 API)即可快速部署服务。凭借原生Go语言编写的高效性和跨平台兼容性,Caddy常被用于轻量化场景,适合开发者和运维人员快速构建安全的网络服务。
Caddy的最新版本是Caddy2,主流版本也是Caddy2。需要注意的是,Caddy和Caddy2的配置文件语法并不完全一样。
📝 安装Caddy
Caddy的安装很简单,由于不使用其他第三方插件,所以可以直接通过系统的包管理器进行安装,例如我使用的是Debian系统:
📝 修改Caddy配置文件
这里我所使用的域名是
notion.dolingou.com
,即通过notion.dolingou.com
域名替代notion.so
域名从而实现反向代理加载位于Notion上的图片。安装完Caddy之后,配置文件位于/etc/caddy/Caddyfile
,你可以使用你喜欢的编辑器进行编辑,例如我使用的是Vim
,添加如下内容:Caddy2配置要点
拒绝所有非来自博客域名请求
涉及代码段:
这部分代码主要是避免这个反向代理被恶意使用,造成反向代理服务器的负载过高出现问题,或者盗刷大量流量。所有非博客域名的请求均会返回
403
错误。你可以将*.dolingou.com
替换为你的域名。处理Caddy反向代理域名根目录请求
涉及代码段:
这部分代码主要用于当用户直接访问根目录及根目录下
/image
时,返回200
请求,并设置响应头的Content-Type
为text/plain
;一方面为特定路径提供简单的占位符响应,另一方面可以快速测试服务器的响应,便于Debug。Caddy反向代理转发配置
涉及代码段:
用于将匹配特定路径的请求代理转发到目标服务器
https://www.notion.so
,并在转发过程中设置一些请求头、Host、Referer、User-Agent和SSL/TLS配置。具体如下:
- 定义匹配器
@imagePath
: @imagePath
是一个匹配器(matcher),用于匹配特定的请求路径。path_regexp image ^/image.*$
:使用正则表达式匹配路径。^/image.*$
:匹配以/image
开头的所有路径,例如/image
、/image/123
、/image/test.jpg
等。- 这个匹配器会捕获所有路径符合正则表达式
^/image.*$
的请求。
- 反向代理配置:
reverse_proxy
是一个指令,用于将请求代理转发到指定的后端服务器。在Caddy 1版本中,反向代理是proxy
@imagePath
:指定匹配器,表示仅对匹配@imagePath
的请求生效。https://www.notion.so
:目标服务器的地址,所有匹配的请求都会被转发到这里。根据NotionNext的默认配置文件NEXT_PUBLIC_NOTION_HOST
的默认值提示,填写notion.so
域名。
- 设置请求头:
header_up
是一个指令,用于设置转发到后端服务器的请求头。Host www.notion.so
:将Host
头设置为www.notion.so
,确保后端服务器知道请求的目标主机。Referer https://www.notion.so
:将Referer
头设置为https://www.notion.so
,模拟请求来源。User-Agent {http.request.header.User-Agent}
:将User-Agent
头设置为客户端原始请求的User-Agent
,确保后端服务器能够识别客户端类型。X-Real-IP {http.request.remote.host}
:将X-Real-IP
头设置为客户端的真实IP地址,用于后端服务器记录或处理。Accept-Encoding ""
:清空Accept-Encoding
头,防止后端服务器返回压缩内容(如果需要)。Accept-Language {http.request.header.Accept-Language}
:将Accept-Language
头设置为客户端原始请求的Accept-Language
,确保后端服务器返回正确的语言内容。X-Cache {http.reverse_proxy.header.X-Cache-Status}
:将X-Cache
头设置为反向代理的缓存状态(如果有)。
- SSL/TLS配置:
transport http
:定义HTTP传输配置。tls
:启用TLS(HTTPS)加密,确保与后端服务器的通信是安全的。tls_server_name www.notion.so
:设置TLS的服务器名称为www.notion.so
,用于SNI(Server Name Indication)验证。
完成以上配置后,直接访问反代域名,这时候浏览器应该会显示一个
200 OK!
,即表示配置成功。- Caddy缓存配置:
我没有像上面Nginx样例中一样为反向代理添加缓存。原因在于目前Caddy2自身没有提供缓存功能,需要通过插件实现。而插件在命中率和缓存污染等方面的实现情况并不是很好。我的博客本身流量也不是很大,而且又有Cloudflare的CDN作为缓存,所以也就没有继续研究Caddy的这部分缓存功能。
- 重启Caddy
在完成上述配置文件修改后,需要对Caddy进行重启
📝 配置Vercel环境变量
完成以上在云服务器的Caddy配置后,在Vercel中的NotionNext项目下添加环境变量
NEXT_PUBLIC_NOTION_HOST
,用于替换默认的Notion Host变量(https://notion.so
)。Vercel环境变量配置的位置位于
Settings
→ Environment Variables
中,新增环境变量:注意需要携带https,否则无法正常使用。添加完成后,需要在Vercel中对NotionNext进行重新部署即可生效。
这时候打开博客的图片,查看图片地址,应该类似于
https://notion.dolingou.pro/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F6d3fda40-6b03-4bf3-842b-4c9bb68a90f1%2F5a7f71fc-218f-4ac0-b76f-e471232cd7647%2Fandroid-chrome-512x512-min.webp?table=collection&id=f87dcb58-ba2a-40bb-a156-53d7877975e9&t=f87dcb58-ba2a-40bb-a156-53d7877975e9&width=800&cache=v2"
这种。如果直接访问这个地址,会通过302
重定向的方式,经由s3.us-west-2.amazonaws.com
,最终到https://img.notionusercontent.com/s3/prod-files-secure%2F6d3fda40-6b03-4bf3-842b-4c9bb68a90f1%2F5a7f71fc-218f-4ac0-b76f-e47602cd7647%2Fandroid-chrome-512x512-min.webp/size/w=800?exp=1741086188&sig=klZmCOx0XSjO_rQwnGGeMEyR_Kuz1dct7Y5cyf3Fdv4
。🤗 Caddy反向代理配置总结归纳
因为我最终还是将反向代理域名使用Cloudflare CDN服务,也就是开启小黄云,所以为反向代理域名配置了SaaS回源使用Cloudflare域名优选(没错,CNAME到了Linux.do),优化国内的访问速度。同时由Cloudflare提供缓存,故未在反向代理服务器的Caddy配置中添加缓存配置。目前的国内访问情况如下,相比使用默认的
Notion.so
,在全国范围内速度提升了不少,延迟基本都控制在1.5s ~ 2s左右,同时在全国范围应该都可以正常访问。
📎 参考文章
有关Caddy安装或者使用上的问题,欢迎您在底部评论区留言,一起交流~