May 1, 2025
By: Kevin

Clojure Kit框架入门介绍

  1. Kit vs Luminus: 第一印象
    1. 创建第一个 Kit 项目
    2. 项目结构概览
    3. Kit 模块: 按需添加功能
    4. 构建留言板: 模块实战
      1. 1. 添加 HTML 页面渲染
      2. 2. 添加数据库支持 (SQLite + HugSQL)
      3. 3. 连接前后端
    5. 运行和打包
    6. 总结与思考

Kit是Luminus的进化, 体验了以下, 做了个项目, 体验很棒, 本文是入手指南. 有兴趣的同事们可以尝试一下公司代码库中hospital这个项目, 应该都有权限.

Kit vs Luminus: 第一印象

Luminus 虽然能快速启动项目, 但初始生成的项目结构和依赖项相当庞杂. Kit 给人的初步印象是更轻量, 它提供了一个更简洁的模板, 允许开发者根据需要逐步添加功能模块.

另一个加分项是 Kit 使用了 clj-new 这个 Clojure CLI 工具来创建项目模板.

创建第一个 Kit 项目

首先需要安装 Kit 的 clj-new 模板. 如没有安装过 clj-new 工具, 它会自动下载.

# 安装 Kit 模板 (如果还没安装过 clj-new 会先下载)
clj -Ttools install io.github.kit-clj/kit-template '{:git/tag "v2.4.6"}' :as kit

注意: 这里使用了 v2.4.6 版本作为示例, 请根据实际情况使用最新或需要的版本

clj-new 源自 Boot 的 boot-new, 而 boot-new 又源自 Leiningen 的 line-new . Sean Corfield 也提到了他创建的 deps-new, 一个更轻量级的, 只关注 deps.edn 项目的模板工具.

安装好模板后, 创建项目就很简单了:

# 使用 kit 模板创建名为 my-guestbook 的项目
clj -T:new :template kit :name my-guestbook

项目结构概览

创建完成后, 进入项目目录 cd my-guestbook, 可以看到主要文件和目录包括:

  • deps.edn: 项目依赖和配置管理 .
  • build.clj: 使用 tools.build 进行构建任务管理 .
  • Dockerfile: 用于 Docker 容器部署 .
  • README.md: 项目文档 .
  • resources/system.edn: 系统配置, Kit 使用 Aero 库来管理配置. Aero 支持 profile, 可以方便地区分开发, 测试和生产环境.
  • src/my_guestbook/core.clj: 应用程序入口, 负责启动和停止系统.
  • 环境特定目录 (env/dev, env/test, env/prod): 包含各环境下的代码, 资源和配置 . 例如 env/dev/src/user.clj 包含方便 REPL 开发的辅助函数 (go, halt, reset) .
  • resources/public/: 存放静态资源 .

Kit 使用 Integrant 来管理组件的生命周期和依赖关系. 这与 Luminus 常用的 Mount 或 Stuart Sierra 的 Component 有所不同.

Integrant 的配置是声明式的, 定义在 system.edn 中, 通过多重方法 (defmethod) 来实现组件的初始化 ig/init-key 和销毁 ig/halt-key.

Kit 模块: 按需添加功能

Kit 的一个核心特性是它的模块系统. 可以先创建一个最小化的项目, 然后根据需要"安装" 额外的功能模块, 比如 HTML 页面渲染, 数据库访问等.

在 REPL 中可以查看和管理模块:

同步所有模块(第一次是需要执行的, 从服务端获得所有模块列表):

(kit/sync-modules)

查看所有模块:

(kit/list-modules)
:kit/sql - adds support for SQL. Available profiles [ :postgres :sqlite ]. Default profile :sqlite
:kit/datomic - adds support for Datomic
:kit/hato - adds support for kit-Hato HTTP client
:kit/simpleui - adds support for HTMX using SimpleUI (previously called ctmx)
:kit/codox - adds support for codox
:kit/html - adds support for HTML templating using Selmer
:kit/sente - adds support for Sente websockets to cljs
:kit/cljs - adds support for cljs using shadow-cljs
:kit/dominoui - adds support for HTMX using SimpleUI and Domino
:kit/dominoui-postgres - adds support for HTMX using SimpleUI and Domino.  Includes sample postgres
:kit/metrics - adds support for metrics using prometheus through iapetos
:kit/auth - adds support for auth middleware using Buddy
:kit/tailwind - adds support for tailwindcss
:kit/devcontainer - adds support for devcontainer. Available profiles [ :default :compose ]. Default profile uses a single docker file.
:kit/nrepl - adds support for nREPL
:kit/htmx - adds support for HTMX using hiccup

安装需要的模块:

(kit/install-module :kit/sql)

使用clj-rewirite, 安装模块会自动修改 deps.edn 添加依赖, 修改 system.edn 添加组件配置, 甚至可能修改 core.clj 等源文件来引入必要的命名空间.

这个自动修改代码的功能虽然强大, 但也让一些参与者表示谨慎, 建议在执行前提交代码到Git.

构建留言板: 模块实战

我们通过安装 :html:sql 模块来构建留言板应用.

1. 添加 HTML 页面渲染

执行 (kit/install-module :kit/html) 后, Kit 会:

  • 添加 Selmer 库依赖, 用于 HTML 模板渲染 . Selmer 类似 Django 的模板引擎, 允许在 HTML 中嵌入逻辑(如循环, 条件判断), 并且对设计师友好 .
  • resources/html 目录下生成基础模板文件(如 home.html, layout.html).
  • 添加处理页面渲染的路由和命名空间(如 my-guestbook.web.routes.pagesmy-guestbook.web.pages.layout).

2. 添加数据库支持 (SQLite + HugSQL)

执行 (kit/install-module :kit/sql)

  • 添加数据库相关依赖: next.jdbc, conman (连接池管理 ), migratus (数据库迁移), 以及 SQLite 驱动.
  • system.edn 中添加数据库连接池 (:db.sql/connection) 和迁移配置 (:db/migrations) .
  • resources/sql/queries.sql 文件中定义 SQL 查询. HugSQL 通过 SQL 文件中的特殊注释(如 -- :name save-message! :! :n)来定义 Clojure 函数.
  • resources/migrations 目录下生成数据库迁移文件(按时间戳命名, 包含 up.sqldown.sql).

我们定义了创建 guestbook 表的迁移 和保存, 查询留言的 HugSQL 函数.

-- resources/migrations/<timestamp>-add-guestbook-table.up.sql
CREATE TABLE guestbook (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name VARCHAR(255),
  message TEXT,
  timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- resources/sql/queries.sql
-- :name save-message! :! :n
-- :doc saves a message to the database
INSERT INTO guestbook (name, message)
VALUES (:name, :message);

-- :name get-messages :? :*
-- :doc selects all messages from the database
SELECT * FROM guestbook;

HugSQL 将 SQL 语句保留在 .sql 文件中, 通过注释映射到 Clojure 函数, 对于固定的查询很方便.

3. 连接前后端

  • 更新路由 (my-guestbook.web.routes.pages):
    • 在 Integrant 配置中引用数据库查询函数组件 (:query-fn) .
    • 修改主页路由处理函数, 调用 get-messages 查询并将结果传递给 Selmer 模板.
    • 添加处理 POST 请求的路由, 调用 save-message! 控制器函数.
  • 创建控制器 (my-guestbook.web.controllers.guestbook):
    • 创建 save-message 函数, 从请求中获取表单参数, 调用 HugSQL 的 save-message! 函数保存数据, 然后重定向回主页.
  • 更新 HTML 模板 (resources/html/home.html):
    • 使用 Selmer 的 {% for %} 标签遍历 messages 并显示留言列表.
    • 添加一个 HTML 表单, 包含姓名, 留言输入框和提交按钮, 目标指向新添加的 POST 路由 . 别忘了添加 CSRF 保护字段 ({{csrf-field|safe}}).
  • 添加样式: 我们还快速引入了 Bulma CSS 框架来美化页面.

运行和打包

在 REPL 中, 可以通过 (reset) 命令重新加载代码, 应用迁移并重启服务. 访问 http://localhost:3000 就能看到留言板应用了.

当需要部署时, 可以使用 tools.build 来打包成一个独立的 uberjar:

clj -T:build uber

可以运行这个 JAR 文件:

java -jar target/my-guestbook.jar

总结与思考

这次对 Kit 的探索非常有启发性.

优点:

  • 模块化: 按需添加功能, 避免了 Luminus 一开始就引入大量依赖和配置的问题. 可以从一个非常小的 API 服务开始, 然后逐步添加 HTML, 数据库等.
  • 循序渐进的复杂度: 对新手更友好, 不必一开始就面对庞大的系统.
  • 基于 deps.edntools.build: 紧跟现代 Clojure 生态.
  • 强大的 REPL 集成: 通过 kit 命令可以直接在 REPL 中管理模块.

值得注意的点:

  • 自动代码修改: 模块安装时会自动修改代码和配置文件, 需要注意版本控制和潜在冲突 .
  • Integrant: Kit 选择了 Integrant 作为组件管理库, 如果更熟悉 Mount 或 Component, 需要适应一下.
  • HugSQL vs HoneySQL: Kit 默认使用 HugSQL.

Kit 提供了一个现代化, 模块化且对开发者友好的 Clojure Web 开发体验. 它在 Luminus 的基础上做了很多改进, 特别是模块化设计, 使得项目可以从小处着手, 逐步扩展. 对于想要开始 Clojure Web 开发的新手, 或者寻求更灵活框架的开发者来说, Kit 绝对值得一试.

Tags: clojure