为vitepress静态网站增加访问统计代码

最近写自研的一个软件产品文档,首次使用了vitepress。看着官方文档,磕磕绊绊的算是完成了一版。比如:

在为文档网站添加访问统计代码时,遇到了些困难。网上搜索和掘金都没有合适的答案。这里介绍我的具体实现,以供需要的同学使用。

一、vitepress的相关配置

为vitepress静态网站增加统计代码,需要在2个地方进行配置:head 和 路由。

1.1 head 配置

我们要增加网站访问统计代码。无论你用的是google还是百度,或者其他第三方统计服务,都需要在head中进行配置。

在 .vitepress/config.ts 文件中,配置如下:

js 复制代码
 head: [
    // ... 其他部分的配置,比如
    
    [
      'script',
      {},
      `
      window._hmt = window._hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?abcdefgeggsdfsdf123123";
        var s = document.getElementsByTagName("script")[0]; 
        s.parentNode.insertBefore(hm, s);
      })();
      `,
    ],
  ],

由于google无法访问,又不想花银子,所以这里以某度统计的免费版为例。这里代码中和某度统计官方文档不同的地方,在与第 8 行。(不清楚如何将第8行高亮显示,请知道的同学留言告诉我 :))

window._hmt = window._hmt || [];

官网文档中的实例是:var _hmt = _hmt || [];

之所以要写入全局变量window中,是为了下面介绍的第2项配置。在第二项配置中,会读取这个 _hmt 变量。如果不存入 window 对象中,则读取不到。

1.2 路由配置

vitepress是基于文件路径的路由,并且构建生成的都是静态的html页面。根据vitepress的官网介绍,vitepress构建的实质上是一个单页面应用(SPA)。

而用户在这个SPA应用中,会访问不同的静态页面。我们必须把他所有不同的访问url都进行统计记录下来。

在SPA应用中,那么仅仅在head部分增加一个js函数来发送访问统计数据到统计平台,就显得不够了。因为这个js函数在spa中,只会执行一次。

既然是spa,那么页面的跳转,就离不开router,我们只需要跟踪路由的变化即可。

1.2.1 主题配置项

我们先来看看主题的主要配置项:

ts 复制代码
interface EnhanceAppContext {
    app: App;
    router: Router;
    siteData: Ref<SiteData>;
}

interface Theme {
    Layout?: Component;
    enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>;
    extends?: Theme;
    /**
     * @deprecated can be replaced by wrapping layout component
     */
    setup?: () => void;
    /**
     * @deprecated Render not found page by checking `useData().page.value.isNotFound` in Layout instead.
     */
    NotFound?: Component;
}

其中:enhanceApp是一个参数为EnhanceAppContext的函数。而EnhanceAppContext的一个属性是Router类型。我们再来看看这个Router:

ts 复制代码
interface Router {
    /**
     * Current route.
     */
    route: Route;
    /**
     * Navigate to a new URL.
     */
    go: (to?: string) => Promise<void>;
    /**
     * Called before the route changes. Return `false` to cancel the navigation.
     */
    onBeforeRouteChange?: (to: string) => Awaitable<void | boolean>;
    /**
     * Called before the page component is loaded (after the history state is
     * updated). Return `false` to cancel the navigation.
     */
    onBeforePageLoad?: (to: string) => Awaitable<void | boolean>;
    /**
     * Called after the route changes.
     */
    onAfterRouteChanged?: (to: string) => Awaitable<void>;
}

从上面的几个接口定义可以看出,EnhanceAppContext的router属性,实际上是vue-router实例的一个代理包装。它有一个当前路由的对象、go方法(跳转方法)和3个事件。根据3个事件的命名,我们可以发现onBeforeRouteChange事件,就是我们需要的方法。即:在路由改变之前进行处理。

1.2.2 自定义路由改变事件

我原来的主题配置文件 ( .vitepress/theme/index.js ) 是这样的:

ts 复制代码
import './tailwind.postcss';
import DefaultTheme from 'vitepress/theme';
export default { ...DefaultTheme };

我的目的很明确,主要是写文档。vitepress的默认主题我觉着已经够用了。由于对默认的主题样式不熟悉,同时为了增加一些外部的样式以简化文档页面一些自定义的样式,我引入了 tailwind.css,但是主题文件很简单。只导出了默认的主题。

现在对这个文件内容,做出如下改变:

ts 复制代码
import './tailwind.postcss';
import DefaultTheme from 'vitepress/theme';

DefaultTheme.enhanceApp = ({ app, router, siteData }) => {
  router.onBeforeRouteChange = (to) => {
    console.log('路由将改变为: ', to);
    if (typeof _hmt !== 'undefined') {
      _hmt.push(['_trackPageview', to]);
    }
  };
};
export default { ...DefaultTheme };

默认主题对象,是不具有enhanceApp属性的(上面的接口定义,该属性是可选的),因此我们手动定义他的内容即可。

在这改代码中 _hmt 就是上面文档介绍的,存入 window 对象的那个对象,如果不存入window,则在build文档时,会发生错误。其 push 方法,就是向某度统计发送当前路径的数据。

当然,这里的 onBeforeRouteChange 事件实现是向某度统计发送url路径。你可以根据实际的统计平台的接口要求,自己实现这一块的逻辑。原理是一样的。

实际运行情况如下:

可以看到,每一次的路由变化,控制台都输出了要跳转的url。都会发送一个 hm.baidu.com/hm.gif?cc=1... 的远程请求。这个请求地址,正是目标统计平台接收数据的地址。

至此,我们实现了为vitepress静态网站增加访问统计代码的功能目标。

相关推荐
zhifou1234569 小时前
Vue基础(二)
前端·javascript·vue.js
你脑门上的脚印11 小时前
Vue 项目从零实现语音转文字、文字转语音功能(完整可用 + 踩坑指南)
前端·vue.js
lemon_yyds13 小时前
H5 页面嵌入 APP 的 web-view 时-调用原生能力(uniapp)
vue.js
ITmaster073114 小时前
Vibe Coding 时代:Vue 消失了还是 React 太强?
前端·vue.js·react.js
万敏15 小时前
Vue3 全栈实战第七周:错误处理与请求层封装实战记录
vue.js·node.js·全栈
请你吃div16 小时前
Electron 从零开始的新手开发教程
vue.js·windows·electron
咏方舟【长江支流】18 小时前
【前端1】单据编辑 -EasyUI/Vue/React/Bootstrap 主流框架实现订单单据主子表显示和编辑比较,哪个你最易入门?
前端·vue.js·easyui·咏方舟-长江支流·userbaodatagrid
m0_5791466518 小时前
Element UI 表格合并单元格完全指南:从原理到实战
前端·vue.js·elementui
雪芽蓝域zzs18 小时前
Prettier (代码格式化)配置详解
前端·vue.js
运维全栈笔记1 天前
Vue + Spring Boot 前后端分离项目部署笔记(若依 RuoYi-Vue 3.9.2)
运维·服务器·vue.js·spring boot·笔记·开源·开源软件