Vapor 是 Swift 最流行的 Web 網(wǎng)絡(luò)框架。它可以為你的網(wǎng)站或 API 提供精美的頁面展示和簡易的使用方式。
這是Vapor 博客搭建的開篇,我會(huì)跟著這部英文教程:practical-server-side-swift-using-vapor-4,用于記錄從頭開始學(xué)習(xí)到一步步完善基于 Vapor 框架的個(gè)人博客,這一系列文章會(huì)記錄我學(xué)習(xí)中遇到的坑跟一些個(gè)人的想法,希望對Vapor有興趣的同學(xué)可以一起交流。
因?yàn)槲沂且幻鹖OS開發(fā),swift也在項(xiàng)目中使用了3年了,不過之前也沒系統(tǒng)得接觸關(guān)于服務(wù)器端、web端的開發(fā),所以下面的文章內(nèi)容會(huì)以一個(gè)iOS開發(fā)者的視角去學(xué)習(xí)Vapor,希望能開拓更廣的知識面。
環(huán)境
我使用的是 Macos Montetey 系統(tǒng)
swift 版本是:
swift-driver version: 1.26.21 Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)
Target: x86_64-apple-macosx12.0
使用Xcode 版本是:Version 13.2.1 (13C100)
安裝Vapor
安裝的流程可以查看官方文檔的中文翻譯:https://cn.docs.vapor.codes/4.0/install/macos/
或者查看我之前的文章:http://www.itdecent.cn/p/ffde61bcc9c9
新建項(xiàng)目
安裝完成后,就可以通過vapor new 命令在當(dāng)前文件夾下新建vapor 項(xiàng)目了,項(xiàng)目名稱就叫a-Vapor-Blog
$ vapor new a-Vapor-Blog
會(huì)出現(xiàn) Cloning template...
等待一會(huì)克隆模版完成后會(huì)詢問:Would you like to use Fluent?
這里我們選擇 y, 然后會(huì)展示幾個(gè)db的選擇,這里我們選擇 SQLite
然后會(huì)繼續(xù)詢問:Would you like to use Leaf?
這里我們也選擇 y,選擇完后,新項(xiàng)目的配置也完成。
配置解釋
Fluent
Fluent 是個(gè)ORM的庫,ORM 是通過實(shí)例對象的語法,完成關(guān)系型數(shù)據(jù)庫的操作的技術(shù),是"對象-關(guān)系映射"(Object/Relational Mapping) 的縮寫。使用這個(gè)庫的話,做數(shù)據(jù)存儲(chǔ)就不需要直接寫SQL了。非常得方便,所以我們新建項(xiàng)目需要使用到這個(gè)庫去管理數(shù)據(jù)。
Leaf
Leaf是Vapor框架中使用的一種模板語言。模板語言允許傳遞信息給頁面,然后根據(jù)所傳遞的頁面信息來動(dòng)態(tài)的生成最終的HTML。模板語言也為我們開發(fā)過程中節(jié)約代碼提供了方法,我們可以使用模板語言來寫頁面展示代碼,其中可以加入各種參數(shù)變量,不同頁面間也可以復(fù)用之前寫好的代碼塊。個(gè)性頁面顯示方式時(shí),有時(shí)只需要更改一處地方就可以改變所有頁面的顯示方式了。我們可以在一個(gè)模板中嵌套另一個(gè)模板。
我理解是方便寫html 頁面的模版,對我們這個(gè)博客項(xiàng)目有用,所以我們也使用它。
項(xiàng)目目錄
項(xiàng)目已經(jīng)創(chuàng)建好了,讓我們cd到 a-Vapor-Blog 文件夾然后輸入 vapor xcode 打開新建的項(xiàng)目吧
$ cd a-Vapor-Blog
$ vapor xcode
打開項(xiàng)目后可以看到左邊的項(xiàng)目目錄,下面的package Dependencies 在自動(dòng)的拉取依賴。

這是xcode 在自動(dòng)得通過SPM幫我們處理對應(yīng)的依賴庫,依賴的設(shè)置文件在 Package 文件,可以打開看看。
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "a-Vapor-Blog",
platforms: [
.macOS(.v10_15)
],
dependencies: [
// ?? A server-side Swift web framework.
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent-sqlite-driver", from: "4.1.0"),
.package(url: "https://github.com/vapor/leaf.git", from: "4.0.0"),
],
targets: [
.target(
name: "App",
dependencies: [
.product(name: "Vapor", package: "vapor")
],
swiftSettings: [
// Enable better optimizations when building in Release configuration. Despite the use of
// the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release
// builds. See <https://github.com/swift-server/guides/blob/main/docs/building.md#building-for-production> for details.
.unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
]
),
.executableTarget(name: "Run", dependencies: [.target(name: "App")]),
.testTarget(name: "AppTests", dependencies: [
.target(name: "App"),
.product(name: "XCTVapor", package: "vapor"),
])
]
)
可以看到dependencies 那行有四個(gè)依賴:
vaporfluentfluent-sqlite-driver-
leaf
其中后面3個(gè)是我們新建項(xiàng)目時(shí)選擇的,所以會(huì)加進(jìn) SPM 的dependencies里面。所以新建項(xiàng)目時(shí)沒有選擇也沒關(guān)系,后面可以更新這個(gè)package文件去管理依賴。
這里的配置有一些問題,在后面會(huì)說到如何解決。
SPM
Swift Package Manager 是一個(gè)蘋果官方出的管理源代碼分發(fā)的工具,目的是更簡單的使用別人共享的代碼。它會(huì)直接處理包之間的依賴管理、版本控制、編譯和鏈接。從總體功能上來說,與 iOS 平臺(tái)上的 Cocoapods、Carthage 類似。
當(dāng)前新版Xcode 已經(jīng)內(nèi)置SPM了,所以我們能很方便得使用它。
運(yùn)行
等待Xcode 拉取完Shadow后就可以cmd + R 直接運(yùn)行項(xiàng)目了。不過Xcode這時(shí)候出現(xiàn)了編譯報(bào)錯(cuò):
No such module 'Fluent' , 原來是模版里面的代碼里面已經(jīng) import Fluent 了,但是spm的 Package文件雖然有引入fluent的依賴,但是對應(yīng)我們要運(yùn)行的traget沒有設(shè)置到依賴,所以才會(huì)報(bào)錯(cuò)沒找到模塊的異常。下面是修改后的Package文件:
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "a-Vapor-Blog",
platforms: [
.macOS(.v10_15)
],
dependencies: [
// ?? A server-side Swift web framework.
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent-sqlite-driver", from: "4.1.0"),
.package(url: "https://github.com/vapor/leaf.git", from: "4.0.0"),
],
targets: [
.target(
name: "App",
dependencies: [
.product(name: "Vapor", package: "vapor"),
.product(name: "Fluent", package: "fluent"),
.product(name: "FluentSQLiteDriver", package: "fluent-sqlite-driver"),
.product(name: "Leaf", package: "leaf")
],
swiftSettings: [
// Enable better optimizations when building in Release configuration. Despite the use of
// the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release
// builds. See <https://github.com/swift-server/guides/blob/main/docs/building.md#building-for-production> for details.
.unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
]
),
.executableTarget(name: "Run", dependencies: [.target(name: "App")]),
.testTarget(name: "AppTests", dependencies: [
.target(name: "App"),
.product(name: "XCTVapor", package: "vapor"),
])
]
)
可以看到 在target App 下已經(jīng)補(bǔ)充了 "Fluent"、"FluentSQLiteDriver"、"Leaf" 的依賴了。修改完成保存后,Xcode 自動(dòng)處理依賴,然后再次 Run ,成功運(yùn)行了。會(huì)發(fā)現(xiàn)編譯成功了,然后可以看到控制臺(tái)打印出[ NOTICE ] Server starting on http://127.0.0.1:8080 在瀏覽器輸入 http://127.0.0.1:8080 看到 It works! 就是成功啦!
后續(xù)
到這里項(xiàng)目已經(jīng)創(chuàng)建好了,接下來我們就可以為它添磚加瓦了,一起努力吧!