为什么选择 Swift 写服务端?
在 Node.js、Go、Python 百花齐放的服务端世界,Swift 凭借独特的优势正在悄然崛起。对于 iOS/macOS 开发者而言,用同一门语言贯通前后端是最直接的诉求——你不需要在 TypeScript 和 Swift 之间来回切换,可以直接在服务端和客户端共享数据模型(DTO)、验证逻辑甚至部分业务代码。
Swift 的类型系统是所有主流语言中最严格的之一。编译器会在编译期捕获绝大多数错误,运行时 nil 崩溃几乎不存在(可选值 Optional 的强制处理),这使得 Swift 服务端应用在生产环境中的稳定性极高。与 Go 相当的性能、比 Python 快十倍以上的执行速度,让 Vapor 完全能够承载中大型业务场景。
Swift 服务端的优势
- 类型安全,编译期排错
- 与 iOS/macOS 共享模型代码
- async/await 原生并发
- 内存安全,无垃圾回收停顿
- SwiftPM 完善的包管理
适合的业务场景
- Apple 平台 App 的专属后端
- 高并发 API 服务
- 微服务架构中的单个服务
- 全栈 Swift 团队
- 需要共享 Swift Package 的项目
核心概念词典
在动手之前,先理解 Vapor 生态的几个基础名词。这些概念贯穿整个课程,是后续所有内容的地基。
vapor new 快速脚手架项目、vapor run 启动服务、vapor build 编译。安装方式:brew install vapor。app 实例完成。安装与项目创建
Vapor 的安装非常简单,通过 Homebrew 一条命令完成 Toolbox 的安装。Toolbox 本身是一个 Swift 命令行工具,安装后提供 vapor 命令。
swift --version 确认版本 ≥ 6.0,或通过 Xcode 15.3+ 自带的 Swift 6 工具链使用。Linux 部署同样支持 Ubuntu 22.04/24.04。
# 安装 Vapor Toolbox
brew install vapor
# 验证安装
vapor --version
# 创建新项目(交互式,会询问数据库等配置)
vapor new HelloVapor
# 进入项目目录
cd HelloVapor
# 生成 Xcode 项目(可选,用于在 Xcode 中开发)
open Package.swift
# 运行开发服务器(默认监听 8080 端口)
swift run
项目结构详解
执行 vapor new 后,Vapor 会生成一套标准项目骨架。理解每个文件的职责是掌握框架的第一步:
HelloVapor/
├── Package.swift ← 依赖声明(Vapor、Fluent 等)
├── Sources/
│ └── App/
│ ├── entrypoint.swift ← main 入口,创建 Application
│ ├── configure.swift ← 应用配置(数据库、中间件、服务注册)
│ └── routes.swift ← 路由注册入口
│ └── Controllers/ ← 控制器目录(自行创建)
│ └── Models/ ← 数据模型目录(自行创建)
│ └── Migrations/ ← 数据库迁移目录(自行创建)
└── Tests/
└── AppTests/
└── AppTests.swift ← 集成测试
entrypoint.swift 是程序的入口点,负责初始化 Application 对象并调用 configure、routes。configure.swift 是注册所有服务的地方,包括数据库驱动、中间件、认证配置等。routes.swift 是路由注册的入口,但实际路由往往分散到各个 RouteCollection 中。
请求生命周期
理解一个 HTTP 请求从客户端到达 Vapor 服务再返回响应的完整路径,对于调试和性能优化至关重要。Vapor 基于 NIO 的非阻塞模型与传统的"每请求一线程"模型有本质区别。
关键点在于:整个流程中,EventLoop 线程永远不会阻塞等待。数据库查询、网络请求等 I/O 操作全部通过 async/await 挂起,线程在等待期间可以处理其他请求。这就是 NIO 高并发的核心秘密——用少量线程(通常等于 CPU 核心数)服务海量并发连接。
第一个 Hello World
打开 Sources/App/routes.swift,用最简单的代码注册一个路由:
import Vapor
func routes(_ app: Application) throws {
// GET / → 返回纯文本
app.get { req async in
"Hello, Vapor!"
}
// GET /hello/:name → 路径参数
app.get("hello", ":name") { req async throws -> String in
let name = try req.parameters.require("name")
return "Hello, \(name)!"
}
// GET /json → 返回 JSON(自动序列化)
app.get("json") { req async -> Response in
let data = ["message": "Hello JSON", "framework": "Vapor 4"]
return try .init(status: .ok, headers: ["Content-Type": "application/json"],
body: .init(data: JSONEncoder().encode(data)))
}
}
// configure.swift — 最简配置
import Vapor
public func configure(_ app: Application) async throws {
// 端口配置(默认 8080)
app.http.server.configuration.port = 8080
// 注册路由
try routes(app)
}
# 运行服务
swift run
# 另开终端测试
curl http://localhost:8080/
# → Hello, Vapor!
curl http://localhost:8080/hello/World
# → Hello, World!
swift run --enable-test-discovery 可以同时跑测试。开发阶段推荐安装 watchexec 工具配合自动重启:watchexec -e swift swift run,保存代码后自动重新编译运行。
Package.swift 依赖配置(Swift 6)
Vapor 项目通过 Package.swift 声明所有外部依赖。本教程使用 swift-tools-version:6.0,开启 Swift 6 严格并发检查(Strict Concurrency)。相比旧版,主要变化是顶层声明 swiftLanguageVersions: [.v6] 并在 swiftSettings 中启用并发特性:
// swift-tools-version:6.0
import PackageDescription
let package = Package(
name: "MyVaporApp",
platforms: [.macOS(.v14)],
dependencies: [
// Vapor 4.99.x:正式支持 Swift 6 并发模型
.package(url: "https://github.com/vapor/vapor.git", from: "4.99.3"),
// Fluent ORM(Swift 6 兼容版本)
.package(url: "https://github.com/vapor/fluent.git", from: "4.12.0"),
// PostgreSQL 驱动
.package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.10.0"),
// JWT 支持
.package(url: "https://github.com/vapor/jwt.git", from: "4.2.2"),
],
targets: [
.executableTarget(
name: "App",
dependencies: [
.product(name: "Vapor", package: "vapor"),
.product(name: "Fluent", package: "fluent"),
.product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"),
.product(name: "JWT", package: "jwt"),
],
swiftSettings: swiftSettings
),
.testTarget(
name: "AppTests",
dependencies: [
.target(name: "App"),
.product(name: "XCTVapor", package: "vapor"),
],
swiftSettings: swiftSettings
)
],
// Swift 6 语言模式:开启严格并发检查
swiftLanguageVersions: [.v6]
)
// Swift 6 并发特性设置
var swiftSettings: [SwiftSetting] { [
.enableUpcomingFeature("DisableOutwardActorInference"),
.enableExperimentalFeature("StrictConcurrency"),
] }
Sendable,防止数据竞争在运行时出现。swiftLanguageVersions: [.v6] 告诉 SwiftPM 用 Swift 6 语言模式编译,StrictConcurrency 则进一步开启实验性的严格并发规则。Vapor 4.99.x 专门针对 Swift 6 做了适配,路由闭包签名变为 @Sendable。