Cloudflare Worker 实战:将 Trilium 笔记分享页完美映射为根域名博客并过审 AdSense
前言※#
在使用 Trilium 搭建个人笔记系统时,我们通常会利用其“分享”功能将笔记发布为博客。然而,默认的分享路径通常是 notes.xxx.org/share/Index。如果你想直接使用根域名 xxx.org 作为博客入口,并且希望通过 Google AdSense 的审核(要求根域名下必须有内容且存在 ads.txt),简单的 DNS 映射或 Tunnel 直连是无法满足需求的。
本文将分享如何通过 Cloudflare Workers 巧妙地解决域名映射、样式丢失以及 AdSense 验证三大难题。
基于 Cloudflare Worker + Tunnel 的 Trilium 博客边缘映射架构图
1. 核心需求※#
- 根域名访问:输入
xxx.org直接看到博客首页,而不是 Trilium 登录界面。 - AdSense 兼容:在
xxx.org/ads.txt必须能直接读取到广告验证代码。 - 无感中转:不改变浏览器地址栏域名,保持原有的 Cloudflare Tunnel 穿透架构。
2. 初始尝试与遇坑记录※#
坑一:简单的 Redirect 或反向代理导致 404※#
最初只在 Worker 中处理了 ads.txt 的请求,其余请求直接返回 404 Not Found。这导致访问根域名时直接报错,AdSense 爬虫无法抓取首页内容,审核被拒。
坑二:页面“素颜”(样式完全丢失)※#
当我们尝试通过 Worker 抓取首页 HTML 时,发现页面虽然能打开,但没有任何排版和图片。 原因分析: Trilium 的资源路径(CSS/JS/图片)通常是相对路径或 /share/api/...。当域名从 notes.xxx.org 变为 xxx.org 时,浏览器会去 xxx.org/api/... 请求资源,而这些资源在根域名下并不存在。此外,如果 Host 请求头不匹配,Cloudflare Tunnel 可能会直接拒绝连接。
3. 终极解决方案:智能 Worker 脚本※#
通过在 Cloudflare Worker 中编写逻辑,我们实现了一个“透明代理”。它不仅能提供 ads.txt,还能自动补全资源路径并修正 Host 头。
操作步骤:※#
- 创建 Worker:在 Cloudflare 控制台新建一个名为
blog-handler的 Worker。 - 绑定自定义域:在 Worker 的 Settings -> Triggers 中,添加你的根域名
xxx.org。 - 配置 DNS:确保
xxx.org的 DNS 记录类型为Worker,且代理状态为“橙色云彩”。
完整代码实现:※#
export default {
async fetch(request) {
const url = new URL(request.url);
// 你的后台实际访问地址(即原本带 /share 的地址)
const targetBase = "https://notes.xxx.org";
// 1. 处理 Google AdSense 的 ads.txt (优先级最高)
if (url.pathname === '/ads.txt') {
return new Response('google.com, pub-xxxxxxxxxxxxxxxx, DIRECT, f08c47fec0942fa0', {
headers: { 'content-type': 'text/plain;charset=UTF-8' },
});
}
// 2. 构造目标路径映射
let targetPath = url.pathname;
// 场景 A:访问根目录,直接指向 Trilium 的 Index 分享页
if (targetPath === '/' || targetPath === '') {
targetPath = '/share/Index';
}
// 场景 B:补全缺失的路径前缀(解决样式丢失的关键)
// 如果路径不以 /share/ 开头,说明是浏览器请求的相对资源,我们需要手动补上
else if (!targetPath.startsWith('/share/')) {
targetPath = '/share' + targetPath;
}
const newUrl = targetBase + targetPath + url.search;
// 3. 发起请求并修正 Host 头
const modifiedRequest = new Request(newUrl, {
method: request.method,
headers: new Headers(request.headers),
redirect: 'follow'
});
// 必须删除原始请求中的 Host,让 fetch 自动根据 targetBase 设置正确的 Host
// 否则 Cloudflare Tunnel 会因为域名不匹配报错
modifiedRequest.headers.delete("Host");
// 4. (进阶) 增加静态资源缓存,提升加载速度
let response = await fetch(modifiedRequest);
const contentType = response.headers.get("Content-Type") || "";
if (contentType.includes("image") || contentType.includes("css") || contentType.includes("javascript")) {
response = new Response(response.body, response);
response.headers.set("Cache-Control", "public, max-age=3600");
}
return response;
}
};4. 方案总结与优势※#
- 完美解决 AdSense 审核:根域名有内容,
ads.txt位置正确,爬虫满分通过。 - 样式自动修复:通过脚本逻辑自动识别并补全
/share/路径,彻底解决页面乱码。 - 性能不降反升:虽然经过了 Worker 中转,但由于加入了边缘缓存(Cache-Control),图片和 CSS 的二次加载速度远快于直接从 NAS 穿透读取。
- 隐匿后台:用户和爬虫全程感知不到
notes.xxx.org这个二级域名的存在,品牌统一性更强。
5. 常见问题排查(Checklist)※#
- 依然 404? 检查 Worker 是否真的绑定到了
xxx.org。 - 还是没样式? 在浏览器按
F12查看 Network 选项卡,确认红色报错请求的 URL 是否少了/share。 - 不生效? 记得每次修改代码后都要点击 "Save and Deploy",并清理浏览器缓存。
希望这篇指南能帮到同样在使用 Trilium 搭建博客的朋友。如果有更复杂的路径跳转需求,Worker 的灵活性几乎可以满足你所有的想象。