一、网站访问统计插件
目前我使用到的访问统计插件有两个,一个是 不蒜子 busuanzi ,另一个是我目前使用的 Vercount。
二、两个插件使用感受
-
不蒜子大部分人都很推荐使用,但是它有些缺点:
- 使用的人太多的时候,会出现502错误。
- 不蒜子的代码已经过时,使用的是 Referrer 方法进行统计,这种方法在移动端 / Firefox / Safari 上统计不准确。
- 不蒜子的代码使用的是 JSONP 回调,这种方法容易受到 CSRF 攻击威胁网站安全,详情请看:JSONP。
-
Vercount 优化了不蒜子的缺点,并且支持自托管。但它也有一些小缺点:
- 刷新页面后,会先显示之前的缓存数据,再从接口拉取新数据更新到界面上,观感上会有点怪。
- 统计单文章页面访问量,切换页面后,会在
span
中先显示上一个页面的访问数据,再刷新到本页面的访问数据。
这个小缺点 Vercount 提供了解决方法了,可以往下看 六、Vercount优化。
三、插件说明
对于静态网页来说,两款插件调用的方法都特别的简单,只需要两步:
- 在每一个页面引入一个
script
标签; - 在页面中的某个
span
绑定id标签显示。
script
标签需要在网站的每个页面都添加 (无需都显示),否则计数器可能会丢失这些未添加页面的访问计数。
busuanzi id 标签说明:
- busuanzi_container_site_uv 的作用是为防止计数服务访问出错或超时(3秒)的情况下,使整个标签自动隐藏显示,带来更好的体验。这个id可以省略。
- busuanzi_value_site_pv 的作用是异步回填访问数,这个id一定要正确。
- busuanzi_container_site_pv:_site_pv 包裹容器
- busuanzi_container_site_uv:_site_uv 包裹容器
- busuanzi_container_page_pv: _page_pv 包裹容器
包裹容器可以添加样式
style='display:none'
不蒜子执行完毕会自动修改样式将标签显示出来。
- busuanzi_value_site_pv:本站总访问量
- busuanzi_value_site_uv:本站总访客数
- busuanzi_value_page_pv: 本文总阅读量
Vercount 兼容 busuanzi 的 id 标签写法,也可以把前缀 'busuanzi_'
替换成 'vercount_'
。
html
<!-- busuanzi:busuanzi_container_site_pv 可省略 -->
<span id="busuanzi_container_site_pv">
本站总访问量<span id="busuanzi_value_site_pv"></span>次
</span>
<!-- Vercount -->
<span>
本站总访问量<span id="vercount_value_site_pv">Loading</span>次
</span>
四、在 vitepress 项目中使用插件
一般静态网站项目只需要在 html 的 head 中引入 script
标签即可,但是 vitepress
项目实际是比较特殊的 单页应用程序,切换页面并不会触发整个页面的刷新,不会再次触发 script
重载。
ts
// 错误例子
export default defineConfig({
lang: 'zh-Hans',
title: 'My Awesome Project',
description: 'A VitePress Site',
lastUpdated: true,
// 这里配置只会首次触发span能看到数据,切换路由后,数据便丢失了,除非重新刷新整个页面。
head: [
['script',{defer: '',async: '',src: 'https://cn.vercount.one/js'}]
],
})
以上这个做法是不可行的,所以需要在路由中做手脚。为了简化代码操作,利用 hooks 是很方便的方式。
1. 编写一个调用访问量接口的hooks
编写这个 hooks 的作用是,利用 document 创建一个 script
标签,并利用 script
标签调用 url 。
创建一个 useVisitData.ts
文件,复制下面的代码:
ts
// useVisitData.ts
/**
* 网站访问量统计 hooks
*/
function useVisitData() {
const script = document.createElement('script')
script.defer = true
script.async = true
// 调用 Vercount 接口
script.src = 'https://cn.vercount.one/js'
// 调用 不蒜子 接口
// script.src = '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js'
document.head.appendChild(script)
}
export default useVisitData
其实也不算hooks,不要介意这个写法
2. 在路由中调用hooks
场景一:如果希望做一个全站的访问统计,每个页面跳转都要计算到总访问量中去
javascript需要在网站的每个页面都添加 (无需都显示),否则计数器可能会丢失这些未添加页面的访问计数。
在 viepress 路由守卫中调用 hooks,在.vitepress/theme/index.ts
中添加如下代码:
ts
// .vitepress/theme/index.ts
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { inBrowser } from 'vitepress'
// 导入hooks
import useVisitData from '../../hooks/useVisitData'
export default {
extends: DefaultTheme,
enhanceApp({ app, router, siteData }) {
if (inBrowser) {
// 路由加载完成,在加载页面组件后(在更新页面组件之前)调用。
router.onAfterPageLoad = (to: string) => {
// 调用统计访问接口hooks
useVisitData()
}
}
}
} satisfies Theme
场景二:如果希望某些子路由不想统计到总访问量中,或只想个别些页面统计到总访问量中
直接在上面代码添加一个 ignoreList
或者 whiteList
,利用参数 to
判断路由路径即可:
ts
// .vitepress/theme/index.ts
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { inBrowser } from 'vitepress'
// 导入hooks
import useVisitData from '../../hooks/useVisitData'
// 忽略名单
let ignoreList = ['/a', '/b']
export default {
extends: DefaultTheme,
enhanceApp({ app, router, siteData }) {
if (inBrowser) {
router.onAfterPageLoad = (to: string) => {
// 某些页面不计入总访问量中
if (!ignoreList.includes(to)) {
useVisitData()
}
}
}
}
} satisfies Theme
至此,你可以在任何页面(除了忽略名单页面),插入最简单的 span
,就可以显示统计数字了:
vue
<!-- 使用 vercount 就将 busuanzi_value_page_pv 替换成 vercount_value_page_pv -->
<span>
本文总阅读量 <span id="busuanzi_value_page_pv">Loading</span> 次
</span>
3. 编写一个漂亮的统计访问数据的组件
Vercount 是兼容 busuanzi 的 span 的 id 标签的,也可以将前缀替换成 vercount_
。
但是为了统一和后续功能扩展需要,各自用自己的 id 标签比较好。组件例子如下:
vue
// DataPanel.vue
<template>
<!-- busuanzi用法 -->
<div class="text" id="busuanzi_container_site_pv">
<div>本站总访问量</div>
<span id="busuanzi_value_site_pv" class="font-bold">--</span>次
</div>
<div class="text" id="busuanzi_container_site_uv">
<div>本站访客数</div>
<span id="busuanzi_value_site_uv" class="font-bold">--</span>人次
</div>
<!-- Vercount用法 -->
<div class="text">
<div>本站总访问量</div>
<span id="vercount_value_site_pv" class="font-bold">--</span>次
</div>
<div class="text">
<div>本站访客数</div>
<span id="vercount_value_site_uv" class="font-bold">--</span>人次
</div>
</template>
4. 导入组件
在你想要展示的界面中导入组件,例如在首页 index.md
中导入组件,添加根级 <script>
标签:
md
# index.md
---
layout: home
hero:
name: 'Demo'
features:
- title: Feature A
details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
---
# 访问数据组件
<DataPanel />
<script setup lang="ts">
// 导入访问数据组件
import DataPanel from '../components/home/DataPanel.vue'
</script>
现在,刷新界面就可以看到统计数字的变化了。
如果没有部署项目,看到的数字会很大,只需要部署项目后,统计数据就变正常了。
五、 不蒜子 busuanzi.pure.js
插件问题
使用这个插件,如果按照以下配置,会导致刷新页面后统计两次访问量的问题。这个方式可以弃用了。
安装 busuanzi.pure.js 插件:
npm
npm install busuanzi.pure.js
在 .vitepress/theme/index.ts
中调用插件:
ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
// 导入 busuanzi
import { inBrowser } from 'vitepress'
import busuanzi from 'busuanzi.pure.js'
export default {
extends: DefaultTheme,
enhanceApp({ app , router }) {
// 调用接口
if (inBrowser) {
router.onAfterRouteChanged = () => {
busuanzi.fetch()
}
}
},
}
这个方式弃用吧。
六、Vercount优化
看到这的时候,还记得最开始我说的 Vercount 的小缺点吗?
- 刷新页面后,会先显示之前的缓存数据,再从接口拉取新数据更新到界面上,观感上会有点怪。
- 统计单文章页面访问量,切换页面后,会在
span
中先显示上一个页面的访问数据,再更新到本页面的访问数据。
解决办法:
在含有 id 标签 id="vercount_container_site_pv"
的容器添加 style 属性:style="display: none"
,直到正确获取数据后会自动显示出来。例子如下:
vue
<span id="vercount_container_site_pv" style="display: none">
本站总访问量<span id="vercount_value_site_pv"></span>次
</span>
修改 DataPanel.vue 组件里的代码:
vue
// DataPanel.vue
<template>
<!-- busuanzi用法 -->
<div class="text" id="busuanzi_container_site_pv" style="display: none">
<div>本站总访问量</div>
<span id="busuanzi_value_site_pv" class="font-bold">--</span>次
</div>
<div class="text" id="busuanzi_container_site_uv" style="display: none">
<div>本站访客数</div>
<span id="busuanzi_value_site_uv" class="font-bold">--</span>人次
</div>
<!-- Vercount用法 -->
<div class="text" id="vercount_container_site_pv" style="display: none">
<div>本站总访问量</div>
<span id="vercount_value_site_pv" class="font-bold">--</span>次
</div>
<div class="text" id="vercount_container_site_pv" style="display: none">
<div>本站访客数</div>
<span id="vercount_value_site_uv" class="font-bold">--</span>人次
</div>
</template>
不蒜子也有这个优化功能哦!不蒜子本身数字观感优化还是可以的,加不加看自己的需求吧。