0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SwiftでWebサイトを構築しよう

Posted at

Swiftで動的Webサイト

はじめに

今回は、SwiftでServersideのソリューションを開発して形になってきたので、この場を借りて発表したいと思います。実は2025年の夏頃からGitHubやAWSでデモサイトを公開しているのですが、記事などは何も書いていなかったので、Swiftでサーバーサイド開発の可能性に興味がある方がいれば、ぜひ続きを読んでいただけると嬉しいです。

プロジェクトリンク:

きっかけ - Igniteとの出会い

このプロジェクトのきっかけは、Paul Hudson氏の「Ignite」というプロジェクトです。2025年のTry! Swift カンファレンスでも発表されていました。YouTubeでも解説動画が公開されています。

IgniteのアイデアとDSL

アイデアはSwiftのDSL機能を使って、HTMLのような感覚でSwiftのコードが書けるというものでした。Igniteから引用するとこんな感じでWebサイトが書けます。

Text("Swift rocks")
    .font(.title1)

Text(markdown: "Add *inline* Markdown")
    .foregroundStyle(.secondary)

Link("Swift", target: "https://www.swift.org")
    .linkStyle(.button)

Divider()

Image("logo.jpg")
    .accessibilityLabel("The Swift logo.")
    .padding()

HTMLと違ってコンパイルするので、実行時に文法や構造の崩れに気がつくのではなく、ビルド時にエラーになります。余計な心配が一つ減るわけです。というか、なによりワクワクしますよね。

静的サイトの限界

自分もHello Worldサイトで試してみようと思いましたが、ここで一つ気になることに気がつきました。なんと、「Ignite」は静的なサイト構築用だということです。あれ、動的なサイトはできないの?う〜ん、なんか凄く残念です。

アイデア - 動的なSwiftウェブサイト

そこでひらめきました。このResult Builderを活用して、動的なサイトを構築できるのではないかということです。

CGIの考え方を応用

仕組みはこうです。その昔から今もありますが、ApacheのようなウェブサーバーにはCGIをのせる仕組みがあります。URLから /path/to/hello.cgi のようにCGIの実行モジュールを呼び出すと、Cなどで書かれた実行コードでHTMLなどを生成できます。

このCGIに相当するものをSwiftで書いて、それがDSLでHTML風に書ければ、サイト全体をビルドするのではなく、HTMLでいうページ単位をSwiftで書けるのではないかという発想です。

http://example.com/hello/world/index.html の代わりに
http://example.com/hello/world/index.swift を実行してHTMLを生成するイメージです。

ただ、Swiftのソースが呼ばれても困るので、Swiftでコンパイル済みの index という実行可能コードを起動してHTMLを生成させます。やっぱり、ただのCGIですね。

さらに言ってしまえば、C++や他の言語でも可能ですが、DSLでHTMLっぽく書こうとするとSwiftは美しく実装できそうです。

アーキテクチャ

ディレクトリ構造

そのまま、パスの先に .swift があっても仕方ないので、srcweb に分けます。Swiftでサイトを作る時は、src の下にHTMLに相当するSwiftコードを書きます。

サイトのコーディングが終わったらビルドします。ビルドは src/ のディレクトリ構造を基に web/bin/ を構築します。src/ 下の .swift ソースはビルドされて、bin/ の相当する場所に実行コードを配置します。

例: src/docs/index.swift → コンパイル → bin/docs/index + web/docs/index.webbin

site-root/
├── src/              # Swiftソースファイル
│   ├── index.swift   # ホームページルート
│   ├── about.swift   # Aboutページルート
│   └── docs/
│       └── index.swift  # Docsインデックスルート
├── web/              # 静的ファイル + .webbinマーカー
│   ├── styles/       # CSSファイル
│   ├── *.webbin      # ルートマーカー(自動生成)
│   └── images/       # 静的アセット
└── bin/              # コンパイル済み実行ファイル(自動生成)
    ├── index         # / 用の実行ファイル
    ├── about         # /about 用の実行ファイル
    └── docs/
        └── index     # /docs 用の実行ファイル

Webサーバーの仕組み

Apacheなどでもできるのかもしれませんが、Webの知識は門外漢なのと、やらせたいことがやや特殊なので、独自に開発することにしました。

リクエスト処理フロー

  1. /docs/index が呼ばれます
  2. ウェブサーバーは site-root/web/docs/index.webbin を探します
  3. .webbin があれば、実行コードが存在する証となります
  4. site-root/bin/docs/index の実行コードを起動します
  5. HTMLを生成してブラウザにレスポンスします

静的ファイルの処理

ウェブサーバーはパスの先が仮に .jpg.css などのリソースであれば、そのまま web/ 下にあるリソースを返します。

これを実現するためには独自のウェブサーバーを開発したり、独自の複雑なビルドの仕組みが必要ですが、構造自体はシンプルです。

実際のコード例

基本的なページ

index.html に相当する index.swift はこんな感じで書きます。SwiftUIっぽいコードだと気がつくと思います。

// src/index.swift
import Swiftlets

@main
struct HomePage: SwiftletMain {
    var title = "Ben's Portfolio"

    var body: some HTMLElement {
        VStack(spacing: 20) {
            H1("Hello, I'm Ben! 👋")
            P("iOS Developer. Swift Enthusiast.")
        }
    }
}

プロパティラッパーの活用

リクエストにクエリパラメータが含まれている場合やCookieを扱う場合は、以下のような書き方をします。

@Query("name") var userName: String?
@Cookie("theme", default: "light") var theme: String?  // デフォルト値を指定

SwiftUIの @State@Binding と同じような感覚で使えます。

クイックスタート

ビルドと実行

# サイトをビルド
./build-site sites/my-site

# サーバーを起動
./run-site sites/my-site

# ブラウザでアクセス
open http://localhost:8080

ホットリロード

開発中はサーバーを起動したまま、変更したルートだけ再ビルドできます。サーバーの再起動は不要です!

# サイトを再ビルド(サーバーは起動したまま)
./build-site sites/my-site

変更された実行ファイルは自動的に置き換わり、次のリクエストから新しいコードが実行されます。これにより、開発サイクルが非常に快適になります。

他のフレームワークとの比較

SwiftletsVaporKituraとは異なるアプローチを取っています:

特徴 Swiftlets Vapor/Kitura
アーキテクチャ ルートごとのプロセス 単一サーバープロセス
ホットリロード ✅ ルート単位で可能 ⚠️ サーバー再起動必要
HTML生成 SwiftUI風DSL テンプレートエンジン
学習曲線 SwiftUI経験者に優しい Web開発の知識が必要
用途 中小規模サイト 大規模API・アプリ

Vaporは大規模なRESTful APIや複雑なWebアプリに向いていますが、SwiftletsはよりシンプルでSwiftUIライクな体験を提供します。

Linuxでの実行

SwiftletsはLinuxのSwiftでビルド・実行可能です。ただ、Linuxのバージョンによっては要求されるSwiftのバージョンが用意できない可能性もあるので注意が必要です。

当方ではAWSのUbuntu Linuxでデモサイトのビルドと実行に成功しています。

デモサイト: http://swiftlet.eastlynx.com:8080

制限事項と適した用途

現在の制限事項

Swiftletsは実験的なプロジェクトであり、以下の制限があります:

  • ⚠️ パフォーマンス: プロセス起動のオーバーヘッド(数ms〜十数ms)があります
  • ⚠️ 開発段階: まだ発展途上です。プロダクション利用は慎重にご検討ください
  • ⚠️ コミュニティ: まだ小さいです。ドキュメントや事例も増やしていく段階です
  • ⚠️ セッション管理: 現在はCookieとファイルベースのストレージで対応(将来的に改善予定)
  • ⚠️ データ永続化: 各ルートが独立したプロセスなので、共有データはファイルやDBで管理する必要があります

状態管理について: 各リクエストが独立したプロセスなので、メモリ上の状態共有はできません。セッションデータやユーザー情報は、Cookieやファイルストレージ、外部データベース(SQLiteなど)を使って管理します。

想定される用途 ✅

  • 個人のポートフォリオサイト
  • 技術ブログやドキュメントサイト
  • 中小規模のWebアプリケーション
  • SwiftUIの知識を活かしたいプロジェクト
  • プロトタイピング・実験的な開発

想定されていない用途 ❌

  • 超高トラフィックのサービス(プロセスオーバーヘッドが問題になる可能性)
  • ミリ秒単位のレスポンスが求められるリアルタイムシステム
  • 複雑なマイクロサービスアーキテクチャ(Vaporの方が適している)
  • エンタープライズ向け本格運用(現時点では試験的)

まとめ

SwiftでWebサイトを構築するという発想は、一見突飛に見えるかもしれません。しかし、以下のようなメリットがあります:

  • 型安全: コンパイル時にエラーを検出できる
  • SwiftUIライクな書き心地: iOSデベロッパーには馴染みやすい
  • シンプルな仕組み: CGIの考え方をモダンに再実装
  • クロスプラットフォーム: macOSでもLinuxでも動作
  • プロセス分離: 1つのルートのクラッシュが他に影響しない
  • ホットリロード: サーバー再起動なしで開発できる

まだまだ発展途上のプロジェクトですが、Swiftでサーバーサイド開発をしたい方、興味のある方はぜひ試してみてください。フィードバックやコントリビューションも大歓迎です!

リンク

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?