【全程免费】cloudflare部署hexo并配置analytics_with_cloudflare记录访问量

记录一下配置过程,前提是已经在cloudflare workers部署了hexo静态网站,然后本文开始在cloudflare workers部署analytics_with_cloudflare服务,并配置hexo页面自动请求服务接口,记录网站和页面访问量(pv&uv)到cloudflare D1数据库,并设置服务接口的跨域和安全性配置。

我们用到的组件:

  • analytics_with_cloudflare浏览量统计服务 开源
  • cloudflare workers 免费
  • cloudflare D1数据库(关系型数据库) 免费
  • cloudflare Rules页面规则 免费
  • cloudflare wrangler服务部署工具 免费
  • hexo + hexo-theme-icarus主题 开源

我们假设:

  • 你已经在cloudflare购买或配置了域名为abc.com
  • 你的hexo博客页面的地址是https://abc.com(如果是子域名也没关系)
  • 将要部署的流量统计服务url希望是https://abc.com/analytics/*

然后我们开始吧!

1. 部署analytics_with_cloudflare

这个工具的逻辑是在cloudflare workers里部署成api接口服务,数据存入cloudflare D1数据库,用户每次打开hexo页面触发请求/api/visit接口,这样一个请求记录一次请求并同时响应回历史访问量。

部署方式参考官方文档 analytics_with_cloudflare 这里我们也一起从头来一遍,尤其是如何把这个服务的接口集成到hexo页面里。

1.1 首先把仓库代码拉下来

拉吧。

1.2 在本地进行初始化配置

1
2
3
4
5
6
7
8
9
10
11
12
cd analytics_with_cloudflare

# wrangler是cloudflare官方的一个workers部署工具
npm install -g wrangler
npm install hono

# 跳转cloudflare网页授权
npx wrangler login

# wrangler自动创建cloudflare D1数据库和表,web_analytics是数据库名
npx wrangler d1 create web_analytics
# 命令执行成功后会响应一个database_id,自己记录一下

把上边返回的database_id配置到当前目录下的wrangler.toml文件中

wrangler.toml
1
2
3
4
5
6
7
8
9
10
11
name = "analytics_with_cloudflare"
main = "src/index.ts"
compatibility_date = "2024-06-14"

[[d1_databases]]
binding = "DB" # available in your Worker on env.DB
database_name = "web_analytics" # 数据库名也要和你刚才创建的对应上
database_id = "这里填写你的database_id"

[observability.logs]
enabled = true

初始化D1数据表

1
npm run initSql

到这一步,我们在本地初始化了analytics_with_cloudflare,并远程创建了cloudflare D1数据库表。此时还没有把此服务部署到cloudflare workers里,先不要急着npm run deploy,我们先修改一些配置。

1.3 修改代码以支持查看全站访问量

analytics_with_cloudflare默认只能查看每个文章自己的访问量pv&uv,我们修改代码来支持接口返回全站的访问量。找到src/index.ts文件并编辑。

src/index.ts
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
const url_path = body.url
const referrer = body.referrer
const pv = body.pv
const uv = body.uv

// 第一步:添加下边两行代码
const spv = body.spv
const suv = body.suv

let referrer_path = ''
let referrer_domain = ''

//忽略中间一大堆代码...

// 第二步:下边这行代码修改,添加了spv suv
const resData:{pv?: number, uv?: number, spv?: number, suv?: number} = {}
if (pv){
const total = await c.env.DB.prepare('SELECT COUNT(*) AS total from t_web_visitor where website_id = ? and url_path = ?').bind(websiteId, url_path).first('total');
resData['pv'] = Number(total)
}
if (uv){
const total = await c.env.DB.prepare('SELECT COUNT(*) AS total from (select DISTINCT visitor_ip from t_web_visitor where website_id = ? and url_path = ?) t').bind(websiteId, url_path).first('total');
resData['uv'] = Number(total)
}

// 第三步:添加下边的两大段代码,分别是spv suv的两个if
if (spv){
const total = await c.env.DB.prepare('SELECT COUNT(*) AS total from t_web_visitor where website_id = ?').bind(websiteId).first('total');
resData['spv'] = Number(total)
}
if (suv){
const total = await c.env.DB.prepare('SELECT COUNT(*) AS total from (select DISTINCT visitor_ip from t_web_visitor where website_id = ?) t').bind(websiteId).first('total');
resData['suv'] = Number(total)
}
// 上边都改完了,后边的代码都别动了
return c.json({ret: "OK", data: resData});

你先别急着部署,我们接着修改一下代码来

1.4 修改代码以限制跨域

我们部署的访问量统计接口默认是公开的,需要做一些限制。我们修改默认的接口名,配置跨域。
还是修改刚才的src/index.ts文件,找到下边类似的代码块:

src/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
// 第一步:我们把原本的 /api/* 改成 /analytics/* 来明确设定这是一个网站分析接口,你不改也行
app.use('/analytics/*', cors({
origin: [
// 'https://def.com', // 你也可以配置多个域
'https://abc.com' // 第二步:这里设置成你hexo静态页面的域名
],
// origin: "*",
allowMethods: ['POST', 'GET', 'OPTIONS'], // 第三步:设置请求方法
}));

app.post('/analytics/visit', async (c) => { // 第四步:同样修改 /api/* 改成 /analytics/* 和上边保持一致
const retObj = {ret: "ERROR", data: null, message: "Error, Internal Server Error"};
// 后边一大堆代码上一步改过了,这一步别动了。

上边代码的修改参考了 https://bytejog.com/posts/hugo/hugo_analytics/#analytics_with_cloudflare%e6%9c%8d%e5%8a%a1%e9%83%a8%e7%bd%b2

1.5 执行部署

1
npm run deploy

执行上边的命令,出现如下成功提示,这个流量统计服务就部署完成了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

> analytics_with_cloudflare@0.0.0 deploy
> wrangler deploy


⛅️ wrangler 4.27.0
───────────────────
Total Upload: 61.66 KiB / gzip: 14.42 KiB
Your Worker has access to the following bindings:
Binding Resource
env.DB (web_analytics) D1 Database

Uploaded analytics_with_cloudflare (3.64 sec)
Deployed analytics_with_cloudflare triggers (0.40 sec)
https://analytics_with_cloudflare.你的账户名字.workers.dev
Current Version ID: 9999-9999-9999-9999-9999

1.6 配置workers访问路径

cloudflare workers都会有一个默认给你的访问域名,我们想要的效果是,假如你的hexo网址是https://abc.com,那么网站流量统计服务也要在你的这个域下边,作为https://abc.com的一个资源来使用,也就是我们要访问https://abc.com/analytics/visit才对。

在你的cloudflare后台里找到计算Workers -> Workers和Pages -> 打开analytics_with_cloudflare -> 找到此服务的设置 -> 域和路由点击添加 -> 侧边窗口里选择路由

如下图依次选择区域就是你在cloudflare里购买或配置的主域名,这个主域名同时也是你的hexo静态博客的域名,路由就是你要访问此服务的url,

如果你的hexo网站在子域也没关系,比如https://blog.abc.com,这个和主域是一样的配置方式,路由里写https://blog.abc.com/analytics/*就行了。

提交配置后就自动生效了,我们来验证一下:

1
2
3
4
5
6
7
8
9
curl -X POST   https://abc.com/analytics/visit   -H 'Content-Type: application/json'   -d '{
"hostname": "test.com",
"url": "/test-path",
"referrer": "",
"pv": true
}'

# 收到下边的响应OK就是对了。如果没收到响应或者收到空响应肯定是不对的。
{"ret":"OK","data":{"pv":6}}

2. 在hexo博客页面里配置以记录访问量

2.1 创建analytics.js

思路就是把analytics_with_cloudflare里边的js文件放到hexo目录里,并修改hexo的代码引用此js文件。

hexo我使用的主题是icarus https://github.com/ppoffice/hexo-theme-icarus 其他主题自行找到对应要修改的文件位置。
因为要修改主题的代码,所以提前自己下载主题的代码,并放到themes/目录下并在hexo配置里添加主题名。

注意你下载的主题代码文件夹大概率叫hexo-theme-icarus之类的,你要自己修改这个文件夹名为icarus并配置到hexo的_config.yml里,不然hexo找不到你修改的主题会自动去下载原版主题代码。

先从刚才鼓捣半天的analytics_with_cloudflare目录下找到front/dist/index.js文件,把这个文件复制到你的hexo项目目录themes/icarus/source/js/并改名为analytics.js,然后我们开始编辑analytics.js文件来添加全站访问量统计和查询:

analytics.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
WebViso.page_pv_id = "page_pv"; 
WebViso.page_uv_id = "page_uv";

// 第一步:添加下边两行代码
WebViso.site_pv_id = "site_pv";
WebViso.site_uv_id = "site_uv";

if(dataBaseUrl) {
BASE_API_PATH = dataBaseUrl;
}
if(dataPagePvId) {
WebViso.page_pv_id = dataPagePvId;

// 跳过大一堆代码

WebViso.init = async function () {
const thisPage = getLocation(window.location.href);
const pagePvEle = document.getElementById(WebViso.page_pv_id);
const pageUvEle = document.getElementById(WebViso.page_uv_id);

// 第二步:添加下边两行代码
const sitePvEle = document.getElementById(WebViso.site_pv_id);
const siteUvEle = document.getElementById(WebViso.site_uv_id);

const queryData = {
url: thisPage.pathname,
hostname: thisPage.hostname,
referrer: document.referrer
}
if (pagePvEle) {
queryData.pv = true;
}
if (pageUvEle) {
queryData.uv = true;
}

// 第三步:添加下边两段代码
if (sitePvEle) {
queryData.spv = true;
}
if (siteUvEle) {
queryData.suv = true;
}


await fetchJson(`${BASE_API_PATH}/visit`, queryData)
.then((res) => {
if (res.ret != 'OK') {
console.error('WebViso.init error', res.message);
return;
}
const resData = res.data;
if (pagePvEle) {
pagePvEle.innerText = resData.pv;
}
if (pageUvEle) {
pageUvEle.innerText = resData.uv;
}

// 第四步:添加下边两段代码
if (sitePvEle) {
sitePvEle.innerText = resData.spv;
}
if (siteUvEle) {
siteUvEle.innerText = resData.suv;
}
})

修改完了保存一下,我们再找到hexo目录里的themes/icarus/layout/layout.jsx,找到</body>标签,在它上边添加代码来引用刚才创建的analytics.js

layout.jsx
1
2
3
4
5
    <Search config={config} helper={helper} />
// 在这个位置添加下边这段代码
<script defer src="/js/analytics.js" data-base-url="https://abc.com/analytics"></script>
// 在body标签结束之前
</body>

这里的data-base-url就是你刚才配置过的流量统计服务的接口url了。

2.2 在你需要的地方展示访问量数据

我们把全站的访问量数据放到通用的页脚里,修改hexo的页脚jsthemes/icarus/layout/common/footer.jsx,找到下边这段代码的位置,添加我们的代码:

footer.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<p class="is-size-7">
<span dangerouslySetInnerHTML={{ __html: `&copy; ${siteYear} ${author || siteTitle}` }}></span>
&nbsp;&nbsp;Powered by <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>&nbsp;&&nbsp;
<a href="https://github.com/ppoffice/hexo-theme-icarus" target="_blank" rel="noopener">Icarus</a>&nbsp;&&nbsp;
<a href="https://giscus.app/zh-CN" target="_blank" rel="noopener">giscus</a>
<br />


{/* 其他的代码不用管,我们添加下边的这段代码 */}
全站访问人次:<span id="site_pv"></span>&nbsp;&&nbsp;全站访问人数:<span id="site_uv"></span>


{showVisitorCounter ? <br /> : null}
{showVisitorCounter ? <span id="busuanzi_container_site_uv" dangerouslySetInnerHTML={{ __html: visitorCounterTitle }}></span> : null}
</p>
{copyright ? <p class="is-size-7" dangerouslySetInnerHTML={{ __html: copyright }}></p> : null}

同理把页面访问量加到你自己喜欢的地方:

1
2
本页访问人次:<span id="page_pv"></span>
本页访问人数:<span id="page_uv"></span>

在本地启动查看效果:

1
hexo clean && hexo generate && hexo server

2.3 都改好后执行hexo的部署即可

修改好之后保存并执行hexo的部署到cloudflare workers里,完成后,在你的博客页面里F12就能看到刷新页面自动请求了

3. 完成

至此完成。