Skip to content

Artalk v2.10.0 变更日志与迁移指南

v2.10.0 是 v2.9.1 之后的下一个正式版本。本版本新增页面投票、SSO Token Exchange、MySQL Cloud SQL TLS 和无 CGO 的 SQLite 构建,并重构了 UI 客户端的生命周期、配置与类型系统。

升级前必读

v2.10.0 包含有意保留的接口与行为变更。服务端与 UI 客户端应同步升级;主题、插件、直接调用 HTTP API 或引用 Artalk TypeScript 类型的项目应先按本文完成迁移。

升级检查清单

  • 备份数据库、配置文件和自定义前端资源。
  • 二进制部署确认工作目录和所有相对文件路径;需要保持旧行为时显式传入 -w 和绝对 -c 路径。
  • 自行编译或打包服务端时升级到 Go 1.26.5。
  • 如需修改应用时区,设置 timezoneATK_TIMEZONE 后完整重启 Artalk。
  • 同时升级服务端与 UI 客户端,避免新旧 Vote API 混用。
  • 检查本地与远程界面配置的优先级;默认改为本地配置优先。
  • 搜索 useBackendConfremoteConfModifier、两参数 ctx.inject()、直接赋值 ctx.conf / ctx.$rootartalk.update(...).xxx()
  • 重新编译使用 Artalk 类型或内部 UI 服务的主题与插件。
  • Node.js 工具链使用现代版本;Artalk 仓库的开发基线为 Node.js 22.19 及以上。

主要更新

UI 与交互

  • 新增页面投票,并可显示当前访客的已投票状态(#983#998)。
  • 新增 preferRemoteConf,明确本地与远程界面配置的合并优先级(#1000#1011)。
  • UI 改用依赖注入容器,并重新整理模块、生命周期和公开类型(#1006#1007)。
  • 新增 Artalk UI ESLint 插件,并升级到 v1.0.2(#995#1010)。
  • User-Agent 识别新增 OpenHarmony 和更多浏览器支持(#1087)。
  • 评论链接的 rel 属性新增 ugc#1120)。

服务端与 API

  • 新增 POST /api/v2/sso/exchange,可将受信任 OIDC 身份提供方的访问令牌交换为 Artalk 会话令牌(#1134)。该功能默认关闭;生产环境应只配置受信任的 HTTPS Issuer,且 /userinfo 必须返回 email_verified: true
  • Vote API 现在统一使用目标类型、目标 ID 和选择,并新增投票状态查询接口。
  • 改进配置文件与数据目录查找,保留切换数据目录前的配置文件定位结果(#992)。
  • MySQL 新增 Google Cloud SQL 双向 TLS 配置支持(#1104)。

构建与运行环境

  • SQLite 改用纯 Go 驱动,正式构建不再依赖 CGO,也不再需要单独的 GORELEASER_CROSS 工具链。跨平台产物可由标准 Go 工具链直接构建。
  • Go 工具链升级到 v1.26.5,并更新相关依赖;登录会话的 JWT 实现升级到受维护的 v5 版本。已有 HS256 Token 的声明与签名格式保持兼容,升级服务端不会因此强制用户重新登录。
  • 官方容器的构建与运行基础镜像升级到 Alpine 3.24;Go 构建版本仍固定为 v1.26.5,容器内的数据目录和配置路径保持不变。
  • 更新前端与文档工具链,包括 Vite 8.1、Marked 18.0.7 和 KaTeX 0.17。@artalk/plugin-katex 的 peer 范围仍兼容 KaTeX 0.16.45 至 0.17.x,依赖升级不会强制现有主题同步更换 KaTeX。
  • 新增插件注册表拉取脚本和 npm 已发布版本检查脚本。
  • npm 包使用现代条件导出;不再兼容 Node.js 10 的旧模块解析行为。

文档与本地化

  • 新增土耳其语(tr-TR)和繁体中文配置模板。
  • 新增日语 README。
  • 重设计项目首页,补充多语言内容并优化响应式字号。
  • 文档站集成 Git Changelog。

安全性与可靠性

  • 后端 JWT 解析器升级到 github.com/golang-jwt/jwt/v5,显式限制为 HS256,继续校验过期时间,并新增旧 Token 格式、签名算法和过期行为的回归测试。
  • Markdown HTML 清理器由无修复版本且存在 ReDoS 风险的 insane 切换为持续维护的 DOMPurify,保留原有标签、属性、class、style 和 URL scheme 白名单,并增加恶意标记与 ReDoS 回归测试。
  • 前端锁文件将构建与开发工具链中的 fast-uribrace-expansionjs-yamlundici、Vite 等传递依赖固定到已修复版本;完整工作区依赖审计未发现已知漏洞。
  • Google Cloud SQL TLS 会同时加载服务端 CA、客户端证书与私钥,校验服务器证书和主机名,并要求 TLS 1.2 及以上。三个证书路径必须一起配置,避免部分配置被静默忽略。
  • Vote API 会拒绝非法、非正数、不存在或类型未知的投票目标。投票记录和目标计数在同一数据库事务中更新,任一步骤失败都会回滚。
  • 插件 URL 由服务端过滤:相对 URL 与受信任 URL 可下发给客户端,不受信任的绝对 URL 会被移除。
  • 插件注册表下载仅允许 HTTPS 和限定主机,并限制重定向次数、响应大小与请求时间。
  • npm 版本检查不再通过 Shell 拼接包名,并会把网络或解析错误作为失败返回。
  • 进程时区只在初始化时设置,避免并发请求修改全局时区状态。

突破性变更与迁移

1. 本地界面配置默认优先

v2.9.x 中远程配置会覆盖 Artalk.init() 传入的本地配置。v2.10.0 默认改为本地配置优先:

text
Artalk.init() 本地配置 > 环境变量 > 控制中心 = 配置文件

默认无需新增配置:

js
Artalk.init({
  server: 'https://comments.example.com',
  site: 'My Site',
  locale: 'zh-CN', // 保留本地值
})

如需恢复“远程配置优先”,显式开启:

js
Artalk.init({
  server: 'https://comments.example.com',
  site: 'My Site',
  preferRemoteConf: true,
})

useBackendConf 已废弃并始终按 true 处理。设置为 false 不再阻止客户端读取后端必须提供的配置;它不能替代 preferRemoteConf

2. 删除 remoteConfModifier

remoteConfModifier 不再属于公开配置。请根据用途迁移:

  • 固定覆盖项直接放入 Artalk.init(),默认会优先于远程配置。
  • 需要控制中心优先时使用 preferRemoteConf: true
  • 需要控制首次评论请求时使用 fetchCommentsOnInit
  • 仅需初始化后更新时,监听 created 后调用 update()
js
const artalk = Artalk.init({
  server: 'https://comments.example.com',
  site: 'My Site',
  fetchCommentsOnInit: false,
})

artalk.on('created', () => {
  artalk.update({ locale: 'zh-CN' })
  artalk.reload()
})

不再提供可在插件初始化前任意修改远程配置的等价 Hook。

3. 配置类型区分完整值与输入值

Config 表示已经解析完成的完整配置,ConfigPartial 表示 Artalk.init()update() 和插件配置更新所接受的递归可选输入。

ts
import type { Config, ConfigPartial } from 'artalk'

function createComments(conf: ConfigPartial) {
  return Artalk.init(conf)
}

function readResolvedConfig(conf: Config) {
  console.log(conf.server, conf.pagination.pageSize)
}

过去将 Partial<ArtalkConfig> 用作初始化参数的代码应改用 ConfigPartialArtalkConfig 仍可导入,但现在表示完整配置。

ConfigPartial 会保持函数、DOM 元素、DateRegExp 和数组元素的原始语义,不会再把这些值错误地递归拆成对象字段。

4. DI 注册与解析分离

旧的双参数 ctx.inject(key, value) 注册方式已移除。使用 provide() 注册,使用 inject() 解析:

ts
// v2.9.x
ctx.inject('example', createExample())
const example = ctx.get('example')

// v2.10.0
ctx.provide('example', () => createExample())
const example = ctx.inject('example')

provide() 支持依赖列表与 singleton / transient 生命周期。自定义 TypeScript 服务键应通过声明合并扩展 Services

5. ctx.confctx.$root 不可替换

两者仍可读取,但不能整体赋值。运行时直接赋值会抛出带迁移提示的错误:

ts
// 错误
ctx.conf = nextConf
ctx.$root = nextElement

// 正确
ctx.updateConf(nextConf)
const conf = ctx.getConf()
const root = ctx.getEl()

如需更换根元素,请销毁旧实例并使用新的 el 创建实例。

6. Artalk.update() 返回 void

update() 不再返回 Artalk 实例。将链式调用拆开:

js
// v2.9.x
artalk.update({ pageKey: '/next' }).reload()

// v2.10.0
artalk.update({ pageKey: '/next' })
artalk.reload()

7. 插件初始化与 created 时点

内置插件、本地插件和网络插件现在都会在本地与远程配置完成合并后初始化。网络插件不会再看到仅来自某一端的临时配置。

created 会在所有插件完成初始化后触发,随后触发 mounted。依赖旧时序的插件应把初始化前置逻辑放在插件函数内,把需要完整插件环境的逻辑放到 created 监听器中。

8. Vote HTTP API 与客户端方法

旧的投票端点:

http
POST /api/v2/votes/comment_up/123

新端点:

http
GET  /api/v2/votes/comment/123
POST /api/v2/votes/comment/123/up

target_name 只能为 commentpagechoice 只能为 updown

生成的客户端方法同步调整:

ts
await api.votes.getVote('comment', 123)
await api.votes.createVote('comment', 123, 'up', { name, email })

旧端点和旧 votes.vote() 方法不保留兼容适配器。

9. SQLite 驱动改为纯 Go 实现

服务端 SQLite 驱动由基于 mattn/go-sqlite3 的 CGO 实现切换为 github.com/libtnb/sqlite 提供的纯 Go 实现。正式构建不再依赖本地 C 编译器、CGO_ENABLED=1GORELEASER_CROSS_VERSION 对应的交叉编译工具链。

SQLite 磁盘文件格式没有改变,现有 db.file 数据库可以直接使用,普通部署无需修改数据库配置。升级前仍建议备份数据库;首次使用新版本启动时,Artalk 会照常执行数据库结构迁移。

自行编译或将 Artalk 作为 Go 模块嵌入的项目需要注意:

  • 可以删除 SQLite 构建所需的 C 编译器、CGO 和 Goreleaser Cross 配置。
  • 不要再依赖 mattn/go-sqlite3 专属的构建标签、DSN 参数、C API 或动态扩展加载行为。
  • 如有自定义 SQLite 编译选项、扩展或原生备份工具集成,应使用 v2.10.0 重新执行迁移、并发读写和备份恢复测试。

此变更不影响使用 MySQL、PostgreSQL、MSSQL 的部署。

10. 默认配置和数据目录采用 XDG 规则

未指定 --workdir / -w 时,Artalk 不再始终把启动目录作为工作目录。v2.10.0 的默认查找顺序如下:

  • 配置文件:启动目录、启动目录下的 data$XDG_CONFIG_HOME/artalk/etc/artalk
  • 数据目录:如果启动目录存在 ./data 则保持旧工作目录;否则依次使用 $XDG_DATA_HOME/artalk/var/lib/artalk,均不存在时创建 $XDG_DATA_HOME/artalk

配置文件会在隐式切换数据目录前完成定位,但配置中的数据库、日志、上传目录等相对路径,以及 importexportgen 等命令的相对文件参数,仍然基于最终工作目录解析。

现有目录中已经包含 ./data 的常规部署保持原行为。官方 Docker 镜像也显式指定了工作目录和配置文件,不受此变化影响。

如果二进制部署需要完全保持旧路径语义,请显式指定工作目录和配置文件:

bash
artalk -w /srv/artalk -c /srv/artalk/artalk.yml server

升级前应检查 db.filelog.filenameimg_upload.path、IP 数据库和关键词文件等所有相对路径,避免在新的数据目录中意外创建空数据库或文件。

11. 源码构建要求 Go 1.26.5

go.mod 的最低 Go 版本从 1.22.7 提升到 1.26.5。该变化影响 go install、自行编译、发行版打包和将 Artalk 纳入 Go 构建流程的下游项目。

正式二进制和 Docker 镜像用户无需安装 Go。源码构建环境应升级到 Go 1.26.5;禁用 Go Toolchain 自动下载或处于离线环境的 CI 必须提前安装对应工具链。

12. 应用时区在进程初始化时固定

timezone 配置和 ATK_TIMEZONE 环境变量继续保留,用于设置独立于宿主系统或容器 TZ 的 Artalk 应用时区:

yaml
timezone: Asia/Shanghai
bash
ATK_TIMEZONE=Asia/Shanghai artalk server

时区属于进程级全局状态,v2.10.0 只在 Artalk 进程初始化时设置一次,运行期间不支持动态切换。修改配置文件、环境变量或控制中心中的时区后,必须完整重启 Artalk 进程或容器;仅调用控制中心的“应用配置”不足以切换时区。

13. marked 18 与现代包入口

默认 Artalk 构建继续内置 Markdown 能力;ArtalkLite 不把 marked 打包进自身,需要下游提供兼容的 marked@^18.0.3

Artalk 使用的 MarkedRendererparse()setOptions()use() 和 Tokenizer Extension 均不是 v18 专属 API,但 v14 到 v18 的上游解析细节仍可能影响自定义 Renderer、Tokenizer 或快照输出。使用这些扩展的项目应重新运行 Markdown 测试。

Node.js 10 和依赖旧式包解析的工具链不再受支持。Artalk 仓库开发与构建使用 Node.js 22.19 及以上。

保留的兼容入口

为了给主题和第三方插件留出迁移时间,以下入口在 v2.10.0 仍然存在,但已经标记为 deprecated

旧入口推荐入口
ContextApiContext
DataManagerApiDataManager
EditorApiEditor
ctx.datactx.getData()ctx.inject('data')
ctx.userctx.getUser()ctx.inject('user')
ctx.editorctx.inject('editor')
ctx.listctx.inject('list')
ctx.layerManagerctx.inject('layers')
ctx.checkerLauncherctx.inject('checkers')
ctx.sidebarLayerctx.inject('sidebar')
ctx.editorPlugsctx.inject('editorPlugs')
editor.$eleditor.getEl()
editor.getPlugs()editor.getPlugins()
editor.setReply()editor.setReplyComment()

这些别名仅用于过渡;新代码应直接使用推荐入口。完整公开类型请查看 TypeDoc

其他变更

  • 评论回复按钮改用组件实现。
  • Sidebar 与 Auth UI 已适配新的客户端类型。
  • 新增 npm 发布版本检查与插件注册表生成流程。
  • 固定 Swagger TypeScript 客户端生成器版本并更新命令,避免不同开发环境通过 npx 获取不兼容版本。
  • 更新 GitHub Actions 运行时及制品、缓存、Docker、CodeQL 和 Codecov 相关 Actions;工作流输入与发布产物布局保持不变。
  • 更新前端、Go 和文档依赖,并清理旧测试项目与 CI 配置。

完整提交差异可查看 v2.9.1...v2.10.0

贡献者

页面历史