Chieh’s Blog

 
At a Glance on Swift 服务端

注:语言类话题容易引战。这里只是记录了一些个人感想,如果 swift 从来没有进入过你的视线,不如来 at a glance.

最近考虑捡起十几年前想要学习的 iOS App,才发现这么多年过去了,苹果开发领域发生了巨大的改变。
第一眼印象是 Swift UI 的体验相当丝滑,借鉴了 React / Vue 的理念,简简单单就能实现当年费劲的 UI 布局。其次是 Swift 语言本身。

优雅
Swift 借鉴了 Ruby Lang,算得上一门优雅的语言,这可能是最大的优点。具一个例子

struct User {
    let id: Int
    let name: String
    let email: String?
}

func sendWelcomeEmail(to user: User) {
    guard let email = user.email else {
        print("no email, skip")
        return
    }

    print("sending email to \(email)")
}

不需要大量 if err != nil 清晰可读;再比如没有 TypeScript 一堆 import,诸如此类。

渐渐走向成熟
粗略了解后发现,version 3 之后语法开始定型,再也不像之前每个版本都需要大改。

性能
它的性能预计和 go, rust, C 等接近,不会有 Ruby 或者 node 这类脚本型语言的槽点。
通过这个命令可以编译一个 bin 文件,能够直接运行

swift build -c release
./.build/release/example

缺点:它属于 Apple
就像 C# 是一门优秀的语言,但它属于微软的;Swift 因为属于 Apple 的,注定很难成为服务器开发的主流。生态比其他语言弱太多。

我想,以下的情况只要一条,就适合用 Swift 开发服务端

  • iOS app 端的独立开发者,想只用一门语言搞定全部
  • 追求 Developer Happiness,想要一个优雅的高性能解决方案
  • 学习目的,想要熟悉 Swift 语法,做个小项目练习

别的想不到有什么理由用它

 
发布 npm package 的 access token 会过期怎么办?

在 npmjs 官网可以看到消息,之前老的 access token 将会被禁用,现在需要使用 granular access tokens。而这个新创建的 granular access tokens 会自动过期,每隔几十天就要重新生成一次 token,这也太变态了吧!

如果你使用 GitHub / GitLab 的自动构建工具,就不用担心,现在没有 access token 也可以自动发布到 npm,并且还会有这样一个 badge

Built and signed on
GitHub Actions

怎么设置呢?以我的 u301 包为例讲解。

第一步:在 npm 包设置里正确设置 Trusted Publisher

settings

主要是正确设置 workflow 的文件名。至于 Environment name 是多人协作时使用,假设 commit 是不受信的用户时,可以添加额外审批步骤。如果你只有一个人,可以留空。

第二步:添加 publish.yml

我的例子可以在这里找到完整文件:https://github.com/u301-shortener/u301-js/blob/main/.github/workflows/publish.yml
重点是这个

name: Publish to npm

on:
  push:
    # 只有 git tag 带 v 开头的版本号才会自动发布
    tags:
      - "v*"
jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      # 这里添加的 id-token 可以让最后一行 `npm publish` 无需 access token 就能发布。
      id-token: write

    steps:
    # ......

      - name: Publish to npm
        uses: actions/setup-node@v4
        with:
          node-version: '24'
          registry-url: 'https://registry.npmjs.org'
      - run: npm publish --provenance

第三步:发布

推送完这个 GitHub action 文件后,只要每次在 package.json 增加下版本号,然后

git tag git tag v1.0.0
git push --tags

就能触发自动发布

 
安利一个部署工具: kamal

刚刚部署后发现服务器疯狂报错,一键回滚,开始慢慢 debug。我用的是 kamal,让我生活变得更美好。因此写了这篇文章。

什么样的场景适合?

如果你之前 docker compose 部署就很满意了,那么大概率 kamal 也适合你。kamal 弥补了 docker compose 的一些不足,同时还保持了简单。可参考下面的对照表

docker compose kamal
配置文件 docker-compose.yml config/deploy.yml
Dockerfile 支持 支持
构建镜像 当前机器 可以设置远程机器
源码版本 最新文件 最后一次 git commit 的文件
运行环境 生产环境服务器 本地自动 ssh 连上远程,支持多服务器,类似 ansible
多个进程 --scale 已被废止 很遗憾不支持
证书自动生成
平滑部署
一台机器部署多个网站 得用不同端口 可以同一个,因为带 proxy
自动回滚 不行
部署多台机器 需要 docker swarm 支持

Kamal 是 37signals 的开源产品。
官方网站:https://kamal-deploy.org

如果你需要类似 Vercel 的 UI 界面,像 CoolifyDokploy 这样的方案更适合你。

番外篇:如何只用 kamal-proxy

如果你这台服务器上已经部署了 kamal,想要利用它自带的 kamal-proxy 将本机非 kamal 管理的docker 发布出来,应该怎么办?
举例,有一个 http 端口想要以 https 发布出来,或者以子目录的形式发布,比如 /docs 是单独的文档系统。

其实也很简单。首先要确保容器正确添加到 kamal 的 network。以 docker-compose.yml 举例,

services:
  app:
    networks:
      - kamal
networks:
  kamal:
    external: true

假设这是一个 node app,监听了 3000 端口。你想要把它发布到 www.example.com
重点

  1. 上面添加的 networks 是 kamal
  2. docker exec kamal-proxy kamal-proxy deploy www --host www.example.com --target app:3000 --tls --health-check-path /health

如果你写错了,可以改下参数继续执行,会 update 现有的设置。

  • 查看每个参数的含义 docker exec kamal-proxy kamal-proxy deploy --help
  • 列出所有服务 docker exec kamal-proxy kamal-proxy list
  • 如何升级 kamal-proxy
    首先在本地升级 kamal: gem install kamal 然后在本地运行 kamal proxy reboot 升级远程服务器上的 kamal-proxy
 
最近两年做的一些东西
 
做一个 Plant 模板

突然没有了 React 也没有了 ts,一切回到十几年前。我来试试看能不能自制模板。Source code on Github

安装

cd ~/Library/Containers/xyz.planetable.Planet/Data/Documents/Planet/Templates/
git clone [email protected]:shiny/planet-theme-tealight.git

以下将会是格式测试


代码高亮功能

Bun.serve({
  development: true, 
  fetch(req) {
    throw new Error("woops!");
  },
});

字体 Nunito

https://fonts.google.com/specimen/Nunito

List

  • Item A
  • Item B
  • Item C

Number List

  1. Item 1
  2. Item 2
  3. Item 3

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

段落

十七八年前,我最后一次会见我的母校康耐儿大学的史学大师布尔先生(George Lincoln Burr)。我们谈到英国史学大师阿克顿(Lord Acton)一生准备要著作一部《自由之史》,没有写成他就死了。布尔先生那天谈话很多,有一句话我至今没有忘记。他说,“我年纪越大,越感觉到容忍(tolerance)比自由更重要”。

布尔先生死了十多年了,他这句话我越想越觉得是一句不可磨灭的格言。我自己也有“年纪越大,越觉得容忍比自由还更重要”的感想。有时我竟觉得容忍是一切自由的根本:没有容忍,就没有自由。

 
第一篇文章

Across the Great Wall, we can reach every corner of the world.


Mastodon 的 ActivityPub 协议 称不上真正的去中心化,对于大多数人而言实际上把数据和隐私交给了更不靠谱的个人站长。

像 Planet 这样的方案才是理想中的方式。然而类似方案的 Damus 垃圾信息横流,迅速毁了这个社区。

不知道有没有什么去中心的方案能够发现优质信息,过滤垃圾信息;本质上还是让用户上瘾。