Twikoo 是一个简洁、安全、免费的静态网站评论系统。
主要特点:免费搭建,部署简单,功能很完善,隐私护安全,通知发邮件,管理有内嵌,总之免费又方便
关于后端部署,大家可以看官网,或者这篇 VitePress 资源汇总 - 使用 Twikoo 评论系统。
推荐使用 Vercel 部署
(免费,需配置域名加速访问) 或者 Netlify 部署
(免费)。
这篇主要讲 Vitepress 前端如何集成。
预览

集成步骤
1. 安装 twikoo
sh
pnpm install twikoo
2. 初始化 twikoo 组件
vue
<template>
<div id="twikoo"></div>
</template>
<script setup lang="ts">
import { onMounted, watch } from 'vue'
import { useRoute } from 'vitepress'
const route = useRoute()
const initTwikoo = async () => {
// 判断是否在浏览器环境中
if (typeof window !== 'undefined') {
const twikoo = await import('twikoo')
twikoo.init({
envId: 'https://twikoo.xxx.com/', // 换成你自己配置的域名
el: '#twikoo'
})
}
}
// 监听路由刷新评论
watch(route, () => {
initTwikoo()
})
onMounted(() => {
initTwikoo()
})
</script>
3. 组件插入 Layout 插槽
vue
<script setup lang="ts">
import DefaultTheme from 'vitepress/theme'
import Twikoo from './Twikoo' //评论组件
</script>
<template>
<DefaultTheme.Layout>
<template #doc-after>
<Twikoo />
</template>
</DefaultTheme.Layout>
</template>
美化样式
1. 配置 twikoo
twikoo 配置面板里的插件页签,选择代码高亮主题 coy
,代码复制插件 copyButton
。

2. 自定义 css
以下代码中使用的部分变量,可利用开发者工具在本站查找或自己配置。
scss
.twikoo {
.el-input-group__append,
.el-input-group__prepend,
.el-textarea__inner {
border: 1px solid #DCDFE6;
box-shadow: none;
}
.el-input-group__prepend {
border-right: none;
}
.el-button--small {
height: auto;
}
.el-textarea > .el-textarea__inner {
min-height: 117px !important;
border-radius: var(--weiz-border-radius);
margin-top: var(--weiz-spacing-2xl);
}
.tk-preview-container {
border-radius: var(--weiz-border-radius);
}
.tk-comments-count {
font-size: var(--weiz-font-size-sm);
color: var(--vp-c-text-2);
}
.tk-nick,
.tk-replies .tk-nick-link {
font-size: var(--weiz-font-size-st);
margin-right: var(--weiz-spacing);
color: var(--weiz-primary-color);
}
.tk-tag {
margin-right: var(--weiz-spacing);
}
.tk-comments-container > .tk-comment {
border: solid 1px #F3F4F6;
border-radius: var(--weiz-card-border-radius);
padding: var(--weiz-spacing-6xl);
margin-top: 0;
margin-bottom: var(--weiz-spacing-6xl);
transition: var(--weiz-transition-3);
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
}
.tk-replies-expand > .tk-comment {
border-top: solid 1px #f7f7f7;
padding-top: var(--weiz-spacing-4xl);
}
.tk-content p {
line-height: 1.6;
}
a {
color: var(--weiz-primary-color);
&:hover {
color: var(--weiz-primary-color-light-1);
}
}
// 代码块
div.code-toolbar {
border-radius: var(--weiz-border-radius);
box-shadow: var(--vp-code-block-shadow);
:not(pre)>code[class*=language-], pre[class*=language-] {
background: var(--vp-code-block-bg);
border-radius: var(--weiz-border-radius);
}
pre[class*=language-] {
&::before, &::after {
content: none;
}
&>code {
padding: 0.5em;
border-left: 4px solid var(--weiz-primary-color);
border-radius: var(--weiz-border-radius);
box-shadow: var(--vp-code-block-shadow);
}
}
&>div.toolbar {
z-index: 1;
top: 8px;
right: 8px;
&>.toolbar-item>button {
display: none;
padding: 0 6px;
font-size: 12px;
color: black;
}
}
&:hover>div.toolbar>.toolbar-item>button {
display: block;
}
}
}
.dark .twikoo {
.tk-comments-container > .tk-comment {
border-color: #454545;
&:hover {
box-shadow: 0 4px 12px rgba(255, 255, 255, 0.15);
}
}
.tk-replies-expand > .tk-comment {
border-color: #343434;
}
// 代码块
div.code-toolbar {
pre[class*=language-] {
&>code {
filter: brightness(0.8);
}
}
}
}
3. css 注入主题配置
ts
// 全局样式
import './style/index.scss'