Hexo Next 主题使用 Waline 评论系统

前言

版本说明

本文使用的各软件版本如下,一切教程内容以 Waline 官方文档为准。

软件版本描述
waline0.14.8
next8.3.0
hexo5.4.0
hexo-cli4.2.0
node14.16.1
docker20.10.5
linuxCentOS 7.9.2009

Hexo 评论系统选择

Hexo 各类评论系统的对比可看这里,之前博客一直使用的评论系统是基于 Github Issue 的 Utterances。由于 Utterances 默认没有 CDN 加速,经常造成页面加载完成后无法正常显示 Utterances 的评论区,而且需用用户登录 Github 账号才能评论,因此打算更换博客的评论系统。国外的 Disqus、Hypercomments 暂时不考虑,国内访问被墙的概率很大。Gitment、Gitalk、Gitter 和 Utterances 一样,访问速度不太稳定,且登录 Github 才能评论,暂时也不考虑。这一波排除下来,剩下的方案只有 Valine、Isso、Waline 或者 自建评论系统。考虑到 Valine 依赖 Leancloud 第三方服务,且需要在 Leancloud 额外部署 Valine Admin 才能实现邮件通知与评论管理等功能,这样一来感觉也不靠谱,万一 Leancloud 以后退出商业市场竞争呢?综合考虑下来,最终选择了 Waline 评论系统,一款从 Valine 衍生的带后端评论系统,支持多种部署方式和数据存储方式,这样就可以省去 自建评论系统 的开发成本,同时也可以尽量少依赖第三方服务,增加日后扩展和维护的自由度。

Hexo 评论系统介绍

Valine 评论系统

Valine 是一款基于 Leancloud 的快速、简洁且高效的无后端评论系统,用户无需登录即可评论,目前已有 Hexo、Jekyll、Typecho、Hugo、Ghost 等博客程序在使用。由于 Valine 自身不支持邮件通知支持,因此诞生了 Valine Admin 开源项目;一个对 Valine 评论系统的拓展应用,可增强 Valine 的邮件通知功能;基于 Leancloud 的云引擎与云函数,主要实现评论邮件通知、评论管理、自定义邮件通知模板等功能,而且还可以提供邮件 通知博主@ 通知 的功能。

Waline 评论系统

Waline 一款从 Valine 衍生的带后端评论系统,可以将 Waline 等价成 With backend Valine,采用 Client/Server 架构并基于 NodeJS 开发。Valine 支持 MarkDown 语法、邮件通知、评论管理、多种部署方式多种数据存储方式

Waline
客户端脚本服务端部署数据存储
@waline/clientVercelLeanCloud
MiniValineCloudBaseCloudBase
DockerMongoDB
独立部署 MySQL
SQLite
PostgreSQL
Github

Waline 支持的功能:

  • 邮件通知
  • 微信通知
  • QQ 通知
  • Telegram 通知
  • Akismet 反垃圾评论
  • 文章统计
  • 多语言
  • 自定义语言支持
  • 登录支持
  • 评论管理
  • 评论删除
  • 其它数据库服务支持(已支持 LeanCloud, MySQL, MongoDB, SQLite, PostgreSQL)
  • 基于 IP 的评论发布频率限制
  • 基于关键词的评论过滤限制
  • IP 黑名单
  • 重复内容检测
  • CloudBase 腾讯云开发部署支持
  • 社交登录
  • AWS, GCP, Azure 部署支持
  • 置顶评论
  • 评论赞踩

Docker 部署 Waline

笔者使用 Docker 部署 Waline,数据存储方式选择 MySQL,容器管理工具使用 Docker-Compose。

Doker-Compose 部署 MySQL

下述的配置指定了 MySQL 容器的静态 IP 地址与系统时区,yourPassword 为数据库密码,/usr/local/docker-volumes/mysql 是 MySQL 容器的数据卷目录路径

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
version: "3.5"

services:
mysql:
image: mysql:5.7.26
container_name: waline-mysql
restart: always
privileged: false
environment:
TZ: 'Asia/Shanghai'
MYSQL_ROOT_PASSWORD: yourPassword
ports:
- 3306:3306
networks:
redis-network:
ipv4_address: 172.23.0.3
volumes:
- '/usr/local/docker-volumes/mysql/conf:/etc/mysql/conf.d'
- '/usr/local/docker-volumes/mysql/data:/var/lib/mysql'
- '/usr/local/docker-volumes/mysql/log:/var/log/mysql'
command: --default-authentication-plugin=mysql_native_password

networks:
redis-network:
name: redis-network
driver: bridge
ipam:
config:
- subnet: 172.23.0.0/24

MySQL 数据库表初始化

导入最新的 waline.sql 脚本来创建好 MySQL 的数据库表,相关表的结构如下:

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
CREATE DATABASE waline DEFAULT CHARACTER SET utf8mb4;

CREATE TABLE `wl_Comment` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`comment` text,
`insertedAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip` varchar(100) DEFAULT '',
`link` varchar(255) DEFAULT NULL,
`mail` varchar(255) DEFAULT NULL,
`nick` varchar(255) DEFAULT NULL,
`pid` int(11) DEFAULT NULL,
`rid` int(11) DEFAULT NULL,
`status` varchar(50) NOT NULL DEFAULT '',
`ua` text,
`url` varchar(255) DEFAULT NULL,
`createdAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `wl_Counter` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`time` int(11) DEFAULT NULL,
`url` varchar(255) NOT NULL DEFAULT '',
`createdAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `wl_Users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`display_name` varchar(255) NOT NULL DEFAULT '',
`email` varchar(255) NOT NULL DEFAULT '',
`password` varchar(255) NOT NULL DEFAULT '',
`type` varchar(50) NOT NULL DEFAULT '',
`url` varchar(255) DEFAULT NULL,
`avatar` varchar(255) DEFAULT NULL,
`github` varchar(255) DEFAULT NULL,
`createdAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

构建 Waline 的 Docker 镜像

若不希望自己构建 Waline 的 Docker 镜像,可以直接使用 Waline 官方的 Docker 镜像

1
2
3
4
5
6
# 拉取最新的代码
$ git clone https://github.com/lizheming/waline.git

# 构建镜像
$ cd waline
$ docker build -t lizheming/waline -f packages/server/Dockerfile .

值得一提的是,官方提供的 Dockerfile 默认会使用最新的 Waline 代码来构建 Docker 镜像,若希望使用本地的 Waline 代码来构建 Docker 镜像,需要自行更改 Dockerfile 的内容(如下所示)。为了统一使用东八区时区,建议额外更改系统默认的时区,官方镜像默认设置的是 CST 时间貌似不生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# https://github.com/nodejs/LTS
FROM node:lts AS build
WORKDIR /app
ENV NODE_ENV production
RUN set -eux; \
npm config set registry https://registry.npm.taobao.org; \
npm install --production --silent @waline/vercel
# use local source code
RUN rm -rf /app/node_modules/@waline/vercel/src/*
COPY ./src/ /app/node_modules/@waline/vercel/src

FROM node:lts-buster-slim
WORKDIR /app
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV TZ Asia/Shanghai
ENV NODE_ENV production
COPY --from=build /app .
EXPOSE 8360
CMD ["node", "node_modules/@waline/vercel/vanilla.js"]

Waline 服务端默认会使用最新版本的客户端 JS 库,建议更改 waline/packages/server/src/controller/index.js 源文件来指定客户端 JS 库版本,更改后使用本地代码重新构建 Docker 镜像才会生效

1
2
3
4
5
6
7
8
9
10
<body>
<div id="waline" style="max-width: 800px;margin: 0 auto;"></div> <script src="https://cdn.jsdelivr.net/npm/@waline/client@0.14.8/dist/Waline.min.js"></script>
<script>
new Waline({
el: '#waline',
path: '/',
serverURL: location.protocol + '//' + location.host + location.pathname.replace(/\\/+$/, '')
});
</script>
</body>

若构建 Waline 的 Docker 镜像时,一直卡在 NPM 安装模块的过程里,可以更改对应的 Dockerfile,使用淘宝的 NPM 源来加速 NPM 模块下载

1
2
3
4
5
$ vim packages/server/Dockerfile
...
npm config set registry https://registry.npm.taobao.org; \
npm install --production --silent @waline/vercel
...

Docker-Compose 部署 Waline

在上面 Docker-Compose 配置的基础上,指定 Waline 容器的静态 IP 地址 与 Waline 启动时所需的环境变量

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
version: "3.5"

services:
mysql:
image: mysql:5.7.26
container_name: waline-mysql
restart: always
privileged: false
environment:
TZ: 'Asia/Shanghai'
MYSQL_ROOT_PASSWORD: yourPassword
ports:
- 3306:3306
networks:
redis-network:
ipv4_address: 172.23.0.3
volumes:
- '/usr/local/docker-volumes/mysql/conf:/etc/mysql/conf.d'
- '/usr/local/docker-volumes/mysql/data:/var/lib/mysql'
- '/usr/local/docker-volumes/mysql/log:/var/log/mysql'
command: --default-authentication-plugin=mysql_native_password

waline:
container_name: waline
image: lizheming/waline:latest
restart: always
privileged: false
depends_on:
- mysql
ports:
- 8360:8360
networks:
redis-network:
ipv4_address: 172.23.0.4
environment:
TZ: "Asia/Shanghai"
AKISMET_KEY: "false"
DISABLE_USERAGENT: "true"
SITE_NAME: "Your site name"
SECURE_DOMAINS: "example.cn"
AUTHOR_EMAIL: "example@qq.com"
SITE_URL: "https://www.example.cn"
MYSQL_HOST: 172.23.0.3
MYSQL_PORT: 3306
MYSQL_DB: waline
MYSQL_PREFIX: wl_
MYSQL_USER: root
MYSQL_PASSWORD: yourPassword
volumes:
- /usr/local/waline/data:/app/data

networks:
redis-network:
name: redis-network
driver: bridge
ipam:
config:
- subnet: 172.89.0.0/24

Waline 服务端环境变量说明

Waline 服务端配置的基础环境变量如下:

环境变量名称必填默认值备注
TZ 时区
SITE_URL 站点 URL
SITE_NAME 站点名称
AUTHOR_EMAIL 博主邮箱
SECURE_DOMAINS 安全域名配置,支持逗号分隔配置多个域名,配置后非该域名来源的请求会返回 403 状态码,不配置表示允许所有域名来源
IPQPS60 基于 IP 的评论发布频率限制,单位为秒。默认为 60 秒,设置为 0 不限制
DISABLE_USERAGENTfalse 是否隐藏评论者的 UA,默认为否
COMMENT_AUDIT 评论发布审核开关,默认为否,配置后建议在 Placehoder 上提供文案提示
AKISMET_KEYAkismet 反垃圾评论服务的 Key(默认开启,不用请设置为 false,关闭后可以加快评论提交的速度)
AVATAR_PROXYhttps://avatar.75cdn.workers.dev/ 头像 CDN 代理
  • COMMENT_AUDIT:阅读源代码发现,环境变量中不配置 COMMENT_AUDIT,则默认关闭评论发布的审核功能,只要在环境变量中添加了该属性,无论属性值是什么,都会开启评论发布的审核功能

Waline 服务端配置的 MySQL 环境变量如下:

环境变量名称必填默认值备注
MYSQL_HOST127.0.0.1MySQL 服务的地址
MYSQL_PORT3306MySQL 服务的端口
MYSQL_DBMySQL 数据库库名
MYSQL_USERMySQL 数据库的用户名
MYSQL_PASSWORDMySQL 数据库的密码
MYSQL_PREFIXwl_MySQL 数据表的表前缀
MYSQL_CHARSETutf8mb4MySQL 数据表的字符集

Nginx 反向代理配置

若使用 Nginx 作为 Waline 的反向代理,可参考以下配置内容。

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
server {
listen 80;
listen 443 ssl;
server_name www.example.com

if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}

# SSL 证书
ssl_certificate /usr/local/tengine/cert/waline.techgrow.cn.crt;
ssl_certificate_key /usr/local/tengine/cert/waline.techgrow.cn.key;

# SSL 性能调优
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!AESGCM;
add_header Strict-Transport-Security 'max-age=31536000';

location / {
# 反向代理
proxy_pass http://$server_name;
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;
proxy_set_header REMOTE-HOST $remote_addr;

# 缓存
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
expires 12h;
}
}

Nginx 配置跨域访问

默认情况下,当在 Waline 服务端的环境变量里添加了 SITE_URL 属性,那么 Nginx 的反向代理不再需要配置跨域,Waline 会自动将 SITE_URL 添加到允许跨域的名单里。若 Waline 服务端自带的跨域配置不能满足要求,可以参考以下内容自行配置 Nginx 的跨域。

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
location /comment {
# 清除Waline的跨域Header
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
proxy_hide_header Access-Control-Allow-Credentials;

# 添加自定义的跨域Header
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Origin' always;

# 反向代理
proxy_pass http://$server_name;
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;
proxy_set_header REMOTE-HOST $remote_addr;

# 缓存
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
expires 12h;
}

Waline 运行测试

分别创建并启动 MySQL 与 Waline 容器,然后浏览器访问 http://ip:port/ui/register,打开 Waline 的 Web 管理界面进行注册,第一个注册的用户会被 Waline 默认识别为系统管理员(博主),登录成功后的界面如下:

hexo-waline-ui

若 Waline 的评论系统无法正常访问,可以查看 Docker 的日志来排除问题

1
# docker logs -f --tail 20 waline

Next 主题安装 Waline 插件

安装 Waline 插件

1
2
3
4
5
# 进入博客的根目录
$ cd /blog-root

# 安装插件
$ npm install @waline/hexo-next --save

更改 Next 主题的配置文件 themes/next/_config.yml,添加以下内容,其中 serverURL 是 Waline 服务端的访问 URL,需要自行更改该属性的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Waline
# For more information: https://waline.js.org, https://github.com/lizheming/waline
waline:
enable: true
serverURL: https://waline.example.com # Waline server address url
placeholder: 'Just go' # Comment box placeholder
avatar: mm # Gravatar style
meta: [nick, mail, link] # Custom comment header
pageSize: 10 # Pagination size
lang: zh-cn # Language, available values: en, zh-cn
visitor: false # Article reading statistic
comment_count: true # If false, comment count will only be displayed in post page, not in home page
requiredFields: [] # Set required fields: [nick] | [nick, mail]
libUrl: # Set custom library cdn url

更改 Next 主题的样式

由于 Next 主题默认对所有图片都添加了 display: block; CSS 样式,这会导致 Waline 的表情包图片独立一行显示,需要往 Next 主题里添加以下自定义样式来解决,例如更改样式文件 themes/next/source/css/_common/scaffolding/base.styl

1
2
3
4
5
6
7
.vcontent p img {
display: inline;
}

.vpreview p img {
display: inline;
}

Hexo 构建失败解决方法

若 Next 主题安装 Waline 插件后,执行 hexo g 命令抛出以下异常,这是由于 Hexo 或者 Next 版本过低导致,此时需要升级 Hexo 或者 Next 的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ERROR Render HTML failed: index.html
TypeError: Cannot read property 'parent' of null
at Function.exports.update (/usr/local/hexo/node_modules/cheerio/lib/parse.js:55:26)
at module.exports (/usr/local/hexo/node_modules/cheerio/lib/parse.js:17:11)
at Function.exports.load (/usr/local/hexo/node_modules/cheerio/lib/static.js:22:14)
at Hexo.hexoMetaGeneratorInject (/usr/local/hexo/node_modules/hexo/lib/plugins/filter/meta_generator.js:8:21)
at Hexo.tryCatcher (/usr/local/hexo/node_modules/bluebird/js/release/util.js:16:23)
at Hexo.<anonymous> (/usr/local/hexo/node_modules/bluebird/js/release/method.js:15:34)
at Promise.each.filter (/usr/local/hexo/node_modules/hexo/lib/extend/filter.js:60:50)
at tryCatcher (/usr/local/hexo/node_modules/bluebird/js/release/util.js:16:23)
at Object.gotValue (/usr/local/hexo/node_modules/bluebird/js/release/reduce.js:166:18)
at Object.gotAccum (/usr/local/hexo/node_modules/bluebird/js/release/reduce.js:155:25)
at Object.tryCatcher (/usr/local/hexo/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/usr/local/hexo/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/usr/local/hexo/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromiseCtx (/usr/local/hexo/node_modules/bluebird/js/release/promise.js:641:10)
at _drainQueueStep (/usr/local/hexo/node_modules/bluebird/js/release/async.js:97:12)
at _drainQueue (/usr/local/hexo/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/usr/local/hexo/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/usr/local/hexo/node_modules/bluebird/js/release/async.js:15:14)
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)

Waline 高级配置

客户端使用 CDN

Waline 客户端若想使用 CDN 加速,只需在 Next 主题的 _config.yml 配置文件中,更改 Waline 插件的配置(如下所示)即可。由于 Waline 采用 Client/Server 架构,客户端与服务端的代码必须匹配才能正常运行,因此不建议每次自动都获取最新版的客户端 JS 文件,推荐日后统一更新客户端与服务端的版本。

1
2
3
4
5
6
7
# 获取最新版本的Waline
waline:
libUrl: https://cdn.jsdelivr.net/npm/@waline/client/dist/Waline.min.js

# 获取指定版本的Waline
waline:
libUrl: https://cdn.jsdelivr.net/npm/@waline/client@0.14.8/dist/Waline.min.js

客户端配置用户头像

Waline 同 Valine 一样,目前使用 Gravatar 作为评论列表头像。首先博主或者用户自行使用邮箱登录或注册 Gravatar,然后更改自己的 Gravatar 头像。当在博客评论的时候,留下在 Gravatar 注册时所使用的邮箱即可,或者使用 Waline 客户端提供的登录功能,最后 Waline 会自动根据邮箱地址去 Gravatar 获取用户的头像。目前 Waline 官方默认使用的 Gravatar 镜像服务由 V2EX 提供,镜像地址为 https://cdn.v2ex.com/gravatar/,Waline 客户端还可以通过代码设置 avatarCDN 属性来指定 Gravatar 的 CDN 镜像地址。目前 Waline 非自定义头像有以下 7 种默认值可选:

waline-avatar

在 Next 主题的 _config.yml 配置文件中,可以更改 Waline 插件的配置(如下所示)来指定头像显示的类型

1
2
waline:
avatar: retro

服务端配置评论通知

当博客有用户发布评论或者用户回复评论时,Waline 支持对博主和回复评论作者进行通知。博主评论通知支持邮件、微信、QQ 与 Telegram,回复评论作者仅支持邮件通知。由于篇幅有限,这里仅介绍邮箱通知的配置,其他的通知方式可参考官方文档。邮件通知需要在环境变量中配置以下属性:

  • AUTHOR_EMAIL:博主邮箱,用来区分发布的评论是否是博主本身发布的。如果是博主发布的则不进行提醒通知。
  • SMTP_SERVICE:SMTP 邮件发送服务提供商,可以在 这里 查看所有支持的运营商。如果没在列表中的可以自行配置 SMTP_HOSTSMTP_PORT
  • SMTP_HOST:SMTP 服务器地址,一般可以在邮箱的设置中找到。如果未配置 SMTP_SERVICE 的话该项必填。
  • SMTP_PORT:SMTP 服务器端口,一般可以在邮箱的设置中找到。如果未配置 SMTP_SERVICE 的话该项必填。
  • SMTP_USER:SMTP 邮件发送服务的用户名,一般为登录邮箱。
  • SMTP_PASS:SMTP 邮件发送服务的密码,一般为邮箱登录密码,部分邮箱(例如 163)是单独的 SMTP 密码。
  • SMTP_SECURE: SMTP 邮件发送加密,默认为 true,设置为 false 则不会加密请求
  • SITE_NAME:网站名称,用于在消息中显示。
  • SITE_URL:网站地址,用于在消息中显示。
  • SENDER_NAME:自定义发送邮件的发件人,选填。
  • SENDER_EMAIL:自定义发送邮件的发件地址,选填。
  • MAIL_SUBJECT:评论回复邮件标题自定义
  • MAIL_TEMPLATE:评论回复邮件内容自定义
  • MAIL_SUBJECT_ADMIN:新评论通知邮件标题自定义
  • MAIL_TEMPLATE_ADMIN:新评论通知邮件内容自定义

由于国内腾讯云、阿里云默认封了 25 端口,若 Waline 的服务端是部署在云服务器上,则需要使用 465 端口,并启用 SSL 邮件加密,最后系统防火墙别忘了开放 465 端口

Waline 其他特性

自定义表情包

Waline 支持自定义表情,默认内置了微博表情包,客户端的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
new Waline({
el:'#waline',
serverURL: '<YOUR SERVER URL>',

// 这里设置CDN, 默认微博表情CDN
emojiCDN: 'https://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/',
// 表情title和图片映射
emojiMaps: {
"smile":"e3/2018new_weixioa02_org.png",
"lovely":"09/2018new_keai_org.png",
// ... 更多表情
}
})

若客户端希望使用 Bilibili 的表情包,可以参考以下客户端的代码:

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
new Waline({
el:'#waline',
serverURL: '<YOUR SERVER URL>',

// 设置Bilibili表情包CDN地址
emojiCDN: '//i0.hdslb.com/bfs/emote/',
// 表情title和图片映射
emojiMaps: {
"tv_doge": "6ea59c827c414b4a2955fe79e0f6fd3dcd515e24.png",
"tv_亲亲": "a8111ad55953ef5e3be3327ef94eb4a39d535d06.png",
"tv_偷笑": "bb690d4107620f1c15cff29509db529a73aee261.png",
"tv_再见": "180129b8ea851044ce71caf55cc8ce44bd4a4fc8.png",
"tv_冷漠": "b9cbc755c2b3ee43be07ca13de84e5b699a3f101.png",
"tv_发怒": "34ba3cd204d5b05fec70ce08fa9fa0dd612409ff.png",
"tv_发财": "34db290afd2963723c6eb3c4560667db7253a21a.png",
"tv_可爱": "9e55fd9b500ac4b96613539f1ce2f9499e314ed9.png",
"tv_吐血": "09dd16a7aa59b77baa1155d47484409624470c77.png",
"tv_呆": "fe1179ebaa191569b0d31cecafe7a2cd1c951c9d.png",
"tv_呕吐": "9f996894a39e282ccf5e66856af49483f81870f3.png",
"tv_困": "241ee304e44c0af029adceb294399391e4737ef2.png",
"tv_坏笑": "1f0b87f731a671079842116e0991c91c2c88645a.png",
"tv_大佬": "093c1e2c490161aca397afc45573c877cdead616.png",
"tv_大哭": "23269aeb35f99daee28dda129676f6e9ea87934f.png",
"tv_委屈": "d04dba7b5465779e9755d2ab6f0a897b9b33bb77.png",
"tv_害羞": "a37683fb5642fa3ddfc7f4e5525fd13e42a2bdb1.png",
"tv_尴尬": "7cfa62dafc59798a3d3fb262d421eeeff166cfa4.png",
"tv_微笑": "70dc5c7b56f93eb61bddba11e28fb1d18fddcd4c.png",
"tv_思考": "90cf159733e558137ed20aa04d09964436f618a1.png",
"tv_惊吓": "0d15c7e2ee58e935adc6a7193ee042388adc22af.png",
// ... 更多表情
}
})

多语言支持

Waline 支持多语言,默认内置了以下语言,其中 Waline 的多语言翻译以及字段都是沿用了 Valine 的配置。

  • en
  • jp
  • zh-CN
  • zh-TW

自定义语言只需两步,可以参考以下客户端的代码:

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
// 1.定义 langMode
var langMode = {
"nick": "NickName",
"mail": "E-Mail",
"link": "Website(http://)",
"nickFail":"NickName cannot be less than 3 bytes.",
"mailFail":"Please confirm your email address.",
"sofa": "No comment yet.",
"submit": "Submit",
"reply": "Reply",
"cancelReply": "Cancel reply",
"comments": "Comments",
"cancel": "Cancel",
"confirm": "Confirm",
"continue": "Continue",
"more": "Load More...",
"preview": "Preview",
"emoji": "Emoji",
"expand": "See more....",
"seconds": "seconds ago",
"minutes": "minutes ago",
"hours": "hours ago",
"days": "days ago",
"now": "just now",
"uploading":"Uploading ...",
"uploadDone":"Upload completed!",
"busy":"Submit is busy, please wait...",
"code-98":"Waline initialization failed, please check your version of av-min.js.",
"code-99": "Waline initialization failed, Please check the `el` element in the init method.",
"code-100": "Waline initialization failed, Please check your appId and appKey.",
"code-140":"The total number of API calls today has exceeded the development version limit.",
"code-401": "Unauthorized operation, Please check your appId and appKey.",
"code-403": "Access denied by API domain white list, Please check your security domain."
};

// 2.初始化 Waline
new Waline({
el:'#waline',
path: location.pathname,
serverURL: 'YOUR_SERVER_URL',
langMode: langMode
});

必须严格按照上面的 langMode 格式书写内容

Waline 常见问题

发布评论很慢

发布评论的时候因为一些特殊原因,例如垃圾邮件检测、评论通知都是串联操作。其中垃圾邮件检测使用的是 Akismet 提供的服务,这块由于调用国外服务可能会造成访问过慢,可以通过 AKISMET_KEY=false 环境变量关闭垃圾评论检测功能来定位问题。除了垃圾评论检测服务之外,评论通知中的邮件通知也有可能造成超时,这块建议可以先关闭评论通知再测一下是否是因为该功能导致的过慢。

Waline 版本更新流程

  • 更新 MySQL 数据库表结构
  • 更新 Hexo-Next-Waline 插件
  • 更新 Waline ServerWaline Admin 的代码,重新构建 Docker 镜像
  • 若在 Next 的 _config.yml 文件中,Waline 插件的 CDN 配置里有指定 Waline 客户端的 JS 版本(如下配置),那么还需要更改客户端的 JS 版本,否则默认会使用最新版的 Waline 客户端
1
2
waline:
libUrl: https://cdn.jsdelivr.net/npm/@waline/client@0.14.8/dist/Waline.min.js

Waline 客户端与服务端的代码版本必须匹配,否则 Waline 可能无法正常运行

项目源码

参考博客