Twikoo评论
提示
本文是在 博主One 文章:《配置 twikoo 评论系统》 基础上增加了自己实践过程的一些细节,转载无需和我联系,但请注明文章来源。如果侵权之处,请联系博主进行删除,谢谢~
部署方式
Twikoo 支持多种部署方式:云函数,Vercel,私有部署、Docker.... 具体参见文档:https://twikoo.js.org/backend.html
最原始的方法,也就是直接在服务器上部署,步骤很简单:安装 node → 安装 tkserver → 启动。
$ npm i -g tkserver
$ ln -s /opt/nodejs/node/bin/tkserver /usr/local/bin/tkserver
$ tkserver
然后就可以访问了,地址是:http://服务端IP:8080
Linux 服务器可以用 nohup tkserver >> tkserver.log 2>&1 &
命令后台启动。
提示
可能需要在云服务器上开启 8080 端口的防火墙
还是推荐用 Docker 来部署。我之前是用私有部署,几年后想升级 Twikoo,但是因为 node 版本太老了,导致升级失败... 然后试着升级 node,又是一堆报错...
Docker 部署
docker run --name twikoo -e TWIKOO_THROTTLE=1000 -p 8080:8080 -v ${PWD}/data:/app/data -d imaegoo/twikoo
docker-compose.yaml 内容:
version: "3"
services:
twikoo:
image: imaegoo/twikoo
container_name: twikoo
restart: unless-stopped
ports:
- 8080:8080
environment:
TWIKOO_THROTTLE: 1000
volumes:
- ./data:/app/data
自己实际部署:😜
- 创建并启动一个名为
twikoo
的 Docker 容器
docker run --name twikoo -e TWIKOO_THROTTLE=1000 -p 8426:8080 -v ${PWD}/data:/app/data -d imaegoo/twikoo
并在其中生成了一个 docker-compose.yaml
文件
# 创建名为 `twikoo` 的目录
mkdir /root/twikoo
# 创建docker-compose.yaml 文件并添加以下内容
cat >>/root/twikoo/docker-compose.yaml <<EOF
version: '3'
services:
twikoo:
image: imaegoo/twikoo
container_name: twikoo
restart: unless-stopped
ports:
- 8426:8080
environment:
TWIKOO_THROTTLE: 1000
volumes:
- ./data:/app/data
EOF
# 进入该目录
cd /root/twikoo
# 检查 8080 端口是否已经被其他进程占用
netstat -antlp|grep 8080
# 启动twikoo镜像服务
docker-compose up -d
[+] Building 0.0s (0/0) docker:default
[+] Running 2/2
✔ Network twikoo_default Created 0.0s
✔ Container twikoo Started 0.0s
[root@VM-4-16-centos twikoo]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc43659872fe imaegoo/twikoo "docker-entrypoint.s…" 56 minutes ago Up 56 minutes 0.0.0.0:8426->8080/tcp, :::8426->8080/tcp twikoo
[root@VM-4-16-centos twikoo]#
在私有部署的情况下,在你执行 tkserver 的时候,就会在当前目录创建:
- data 文件夹:存放评论数据、配置等
- tkserver.log:日志文件
因此,有必要在你自己指定的目录下启动 tkserver,方便后期的数据备份、日志分析等。
如果你使用的是 Docker,在上述命令里其实也用了 ${PWD}/data
来指定数据文件的目录,请自行选择。
[root@VM-4-16-centos twikoo]# ls
data docker-compose.yaml
[root@VM-4-16-centos twikoo]# ls data/
db.json db.json.0 db.json.1 db.json.2
[root@VM-4-16-centos twikoo]#
HTTPS配置
理论上这样部署,就完成后台的部分了,但鉴于我的网站用了 HTTPS,而 Twikoo 本身并不支持,因此还需要做反向代理。
我这里配置 HTTPS 是用到cloudflare
- 进入cloudflare,在【账户主页】找到您的域名点击进去(如果没有请添加域名),进去后找到 DNS 记录,添加二级域名
- 类型:A
- 名称:twikoo(自定义就行)
- IPv4:填写服务器的 IP
Nginx配置
upstream twi {
server peterjxl.com:8080; #你的域名+加端口
}
server {
listen 443 ssl;
server_name twikoo.peterjxl.com; #子域名
ssl_certificate /opt/nginxrun/conf/cert/8852603_twikoo.peterjxl.com.pem;
ssl_certificate_key /opt/nginxrun/conf/cert/8852603_twikoo.peterjxl.com.key;
# ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!ADH:!EXPORT56:RC4+RSA:+MEDIUM;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://twi;
}
}
- 自己实际配置
# 进入该目录
cd /etc/nginx/conf.d/
# 创建文件
vim twikoo.seasir.top.conf
[root@VM-4-16-centos conf.d]# cat twikoo.seasir.top.conf
server {
listen 80;
server_name twikoo.seasir.top;
#配置https重定向
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name twikoo.seasir.top;
location / {
proxy_pass http://云服务器ip:8080/; # 实际的后台路径
client_max_body_size 100M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
access_log /var/log/nginx/photo.onedayxyy.cn.https.log;
}
# 用于测试 Nginx 配置文件的语法是否正确
nginx -t
- 配置完成后需要重启 NGINX 服务
nginx -s reload
- 这样访问 https://twikoo.seasir.top/ 就会转发到我的服务器 IP:8080 ,完成反向代理
前端配置
- 编辑
docs\.vitepress\config.ts
文件或者前往查看博主Config配置,修改为如下代码:
comment: {
// provider: "giscus",
provider: "twikoo",
options: {
// twikoo 配置,官网:https://twikoo.js.org/
envId: "填写您自己的twikoo域名",
jsUrl: "https://cdn.staticfile.org/twikoo/1.6.42/twikoo.all.min.js",
},
},
运行验证
pnpm docs:dev
Vercel 部署
提示
本文是在 博主 唯知笔记 文章:《使用 Twikoo 评论系统》 基础上增加了自己实践过程的一些细节,转载无需和我联系,但请注明文章来源。如果侵权之处,请联系博主进行删除,谢谢~
Twikoo 评论,需要部署前后端,包括数据库,操作略有复杂,但是不限制代码托管和服务托管,自定义程度更高。官方文档 https://twikoo.js.org/ ,非常详细,部署步骤如下:
建立数据库
MongoDB AtLas 是 MongoDB Inc 提供的 MongoDB 数据库托管服务。免费账户可以永久使用 500 MiB 的数据库,足够存储 Twikoo 评论使用。
申请 MongoDB AtLas 账号
创建免费 MongoDB 数据库,区域推荐选择离 Twikoo 后端(Vercel / Netlify / AWS Lambda / VPS)地理位置较近的数据中心以获得更低的数据库连接延迟。如果不清楚自己的后端在哪个云服务器和地区,可选择
AWS / Oregon (us-west-2)和香港地区
,该数据中心基建成熟,故障率低,且使用 Oregon 州的清洁能源,较为环保在
Database Access
页面点击Add New Database User
创建数据库用户,Authentication Method
选Password
,在Password Authentication
下设置数据库用户名和密码,建议点击Auto Generate
自动生成一个不含特殊符号的强壮密码并妥善保存。点击Database User Privileges
下方的Add Built In Role
,Select Role
选择Atlas Admin
,最后点击Add User
- 在
Network Access
页面点击Add IP Address
添加网络白名单。因为 Vercel / Netlify / Lambda 的出口地址不固定,因此Access List Entry
输入0.0.0.0/0
(允许所有 IP 地址的连接)即可。如果 Twikoo 部署在自己的服务器上,这里可以填入固定 IP 地址。点击Confirm
保存
- 在
Overview
页面点击Connect
,连接方式选择Drivers
,并记录数据库连接字符串,请将连接字符串中的<username>:<password>
修改为刚刚创建的数据库 用户名:密码,复制Mongodb
连接字符串并妥善保管,后面部署需要用到!然后点击Done
示例
mongodb+srv://数据库用户名
:数据库密码
@cluster0.d1vvzs3.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0
- (可选)默认的连接字符串没有指定数据库名称,Twikoo 会连接到默认的名为 test 的数据库。如果需要在同一个 MongoDB 里运行其他业务或供多个 Twikoo 实例使用,建立加入数据库名称并配置对应的 ACL。 连接字符串包含了连接到 MongoDB 数据库的所有信息,一旦泄露会导致评论被任何人添加、修改、删除,并有可能获取你的 SMTP、图床 token 等信息。请妥善记录这一字符串,之后需要填入到 Twikoo 的部署平台里。
Vercel 部署
- 申请 Vercel 账号,点击以下按钮将 Twikoo 一键部署到
Vercel Deploy
- 进入
Settings
-Environment Variables
,添加环境变量MONGODB_URI
,值为前面记录的数据库连接字符串
- 进入
Settings
-Deployment Protection
,设置Vercel Authentication
为Disabled
,并Save
进入
Deployments
, 然后在任意一项后面点击更多(三个点) , 然后点击Redeploy
, 最后点击下面的Redeploy
等待部署完成,部署完成即可进入
Overview
,点击Domains
下方的链接,如果环境配置正确,可以看到 “Twikoo 云函数运行正常” 的提示,说明部署成功!
- Vercel Domains(包含 https:// 前缀,例如 https://xxx.vercel.app)即为您的环境 id
域名配置
- 部署成功后,修改默认域名为你的子域名,需要去你的域名管理那上修改 DNS 解析。
前端配置
- 安装
twikoo
pnpm install twikoo
- 初始化 twikoo 组件和组件插入 插槽
<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>
<script setup lang="ts">
import Twikoo from './Twikoo.vue'
</script>
<template>
<Teek.Layout>
<template #teek-doc-after-appreciation-before>
<!-- 评论组件 -->
<Twikoo />
</template>
</Teek.Layout>
</template>
配置邮件
前后端都处理好后,界面就能正常展示了,但是我们还要处理下邮件功能。进入您的文章底部,找到评论区的设置,首次打开
设置
按钮后,会有设置密码框,设置一个复杂密码并记住。然后进入配置管理
,选择邮件通知
按照提示输入你的邮箱,邮箱授权码等即可。最后有个邮件测试,测试后,你能收到一封邮件,说明功能可用了
美化样式
twikoo 配置面板里的插件页签,选择代码高亮主题 coy,代码复制插件 copyButton。
自定义 css
// 定义变量
:root {
--hyde-border-radius: calc(0.25rem * 2); // 8px
--hyde-spacing-2xl: calc(0.25rem * 2); // 8px
--hyde-font-size-sm: 0.875rem; // 14px
--hyde-font-size-st: 1rem; // 16px
--hyde-spacing: 0.25rem; // 4px
--vp-code-link-hover-color: #79bbff;
--hyde-spacing: 0.25rem; // 4px
--hyde-card-border-radius: 0.25rem * 4; // 16px
--hyde-spacing-6xl: 0.25rem * 6; // 24px
--hyde-transition-3: all 0.3s; // 0.3s
--hyde-card-border-radius: calc(0.25rem * 2); // 8px
--hyde-primary-color-dark: rgb(51.2, 126.4, 204);
--hyde-primary-color: #409eff;
--hyde-font-size-xs: 0.75rem; // 12px
}
.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(--hyde-border-radius);
margin-top: var(--hyde-spacing-2xl);
}
.tk-preview-container {
border-radius: var(--hyde-border-radius);
}
.tk-comments-count {
font-size: var(--hyde-font-size-sm);
color: var(--vp-c-text-2);
}
.tk-nick,
.tk-replies .tk-nick-link {
font-size: var(--hyde-font-size-st);
margin-right: var(--hyde-spacing);
color: var(--hyde-primary-color);
}
.tk-tag {
margin-right: var(--hyde-spacing);
}
.tk-comments-container > .tk-comment {
border: solid 1px #f3f4f6;
border-radius: var(--hyde-card-border-radius);
padding: var(--hyde-spacing-6xl);
margin-top: 0;
margin-bottom: var(--hyde-spacing-6xl);
transition: var(--hyde-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(--hyde-spacing-4xl);
}
.tk-content p {
line-height: 1.6;
}
a:not(.tk-ruser):not(.tk-nick-link) {
color: var(--hyde-primary-color-dark);
font-weight: 500;
text-underline-offset: 2px;
text-decoration: underline;
&:hover {
color: var(--hyde-primary-color);
}
}
// 代码块
div.code-toolbar {
border-radius: var(--hyde-border-radius) !important;
box-shadow: var(--vp-code-block-shadow);
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: var(--vp-code-block-bg);
border-radius: var(--hyde-border-radius);
}
pre[class*="language-"] {
&::before,
&::after {
content: none;
}
& > code {
padding: 1em;
border-left: 4px solid var(--hyde-primary-color);
border-radius: var(--hyde-border-radius);
}
}
& > div.toolbar {
z-index: 1;
top: 8px;
right: 8px;
& > .toolbar-item > button {
display: none;
padding: 0 6px;
font-size: var(--hyde-font-size-xs);
color: black;
}
}
&:hover > div.toolbar > .toolbar-item > button {
display: block;
}
}
.tk-admin-container {
z-index: 1;
}
}
.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);
}
}
}
}
- css 注入主题配置
在docs\.vitepress\theme\styles\index.scss
中添加配置
@use "./comment.scss" as *; // 评论样式