前言
最早期的網頁開發大多依賴極易產生資安漏洞的 CGI 程式。直到 Ruby on Rails 問世並引領風潮後,「網頁框架(Web Framework)」正式成為顯學,並主宰了網頁程式設計長達多年。
然而,時至今日,你很有可能不再需要花費大量時間去學習網頁框架。
現代開發的關鍵在於:專注於業務邏輯,並根據架構分層來部署程式。善用科技巨頭們現成的基礎設施,省下手寫與維護網頁框架的時間,才是當前最高效、最經濟的開發方式。
接下來,本文將由淺入深,為你逐層剖析每個架構層級及其對應的技術棧(Tech Stack)。
Frontend(前端)
這是指直接在使用者瀏覽器中執行的代碼。扣除作為靜態 UI 的 HTML 與 CSS,核心運用的技術棧主要是 JavaScript 以及近年興起的 WebAssembly。
在規劃前端架構時,有以下三個關鍵考量:
- 代碼體積與載入速度:由於下載代碼需要時間,為了維持良好的使用者體驗,整個頁面的代碼量必須嚴格控制,建議維持在數百 KB 以內。
- 效能優化策略:在絕大部分的應用場景下,JavaScript 的執行效能已綽綽有餘。開發時建議先以 JavaScript 實作,只有在遇到極端效能瓶頸時,才考慮引入 WebAssembly。
- 程式碼安全性:Frontend 代碼最終會全數下載到客戶端,這意味著使用者可以輕易檢視你的原始碼。因此,在設計時必須嚴格過濾,確保敏感邏輯與金鑰絕不暴露在前端。
Edge Function(邊緣函數)
這是近年極受矚目的新興架構。在網頁開發的分類中,它屬於後端範疇,但在地理位置上它部署於離使用者最近的邊緣節點(CDN),因此能提供極低的網路延遲(Latency)。
在技術特性與開發上,有以下幾個核心要點:
- 執行環境:Edge Function 運行的環境通常是輕量化的 Chrome V8 Isolate,而非完整的 Node.js,因此開發時主要使用 JavaScript 或 TypeScript。
- 嚴格的資源限制:基於效能考量,平台對程式體積與運行時間(CPU Time)都有嚴格限制。一般而言,程式壓縮後的體積必須控制在 1-2 MB 左右。
- 單一進入點架構:實際上開發者所撰寫的,就是一個簡單的 JavaScript 函數——接收 Request、處理後回傳 Response。它就像是一個單一進入點的微型網頁伺服器(Micro Web Server)。
以下是一個典型的範例程式碼片段:
export default async (request, context) => {
return Response.json({ message: "Hello, World!" });
};
export const config = {
path: "/hello-json",
};
Function as a Service (FaaS)
FaaS(函數即服務)本質上是一個微型的容器或虛擬機,因此在技術棧上幾乎沒有限制。然而,由於 FaaS 的計費模式取決於程式體積與運行時間,為了節省預算,架構上會更傾向使用高效率的「編譯型語言」(如 Golang、Rust、C++),而非自帶 Runtime 的解釋型語言。
在這個層級,依然完全不需要網頁框架。
以 Google Cloud Functions 所提供的 C++ 標頭檔(SDK)為例:
// google/cloud/functions/function.h
class Function {
public:
~Function();
friend bool operator==(Function const& lhs, Function const& rhs) {
return lhs.impl_ == rhs.impl_;
}
friend bool operator!=(Function const& lhs, Function const& rhs) {
return !(lhs == rhs);
}
private:
friend class functions_internal::FunctionImpl;
explicit Function(std::shared_ptr<functions_internal::FunctionImpl> impl);
std::shared_ptr<functions_internal::FunctionImpl> impl_;
};
這個設計的關鍵在於:Function 的核心建構子被宣告為 explicit 且列為私有,開發者必須透過 SDK 提供的介面去實作核心邏輯,FaaS 平台才能順利驅動它。
以下是一個具體實作 Function 的簡短範例:
#include <google/cloud/functions/function.h>
namespace gcf = ::google::cloud::functions;
gcf::Function HelloWorld() {
return gcf::MakeFunction([](gcf::HttpRequest const& /*request*/) {
return gcf::HttpResponse{}
.set_header("Content-Type", "text/plain")
.set_payload("Hello World\n");
});
}
除了平台所必需的膠水程式碼(Glue Code)之外,開發者所撰寫的核心業務邏輯,在結構上可以跟「網頁框架」毫無關聯。
網路上經常看到「在 FaaS 裡面塞進整個網頁框架(例如在 AWS Lambda 裡跑 Express/Django)」的教學範例,這在架構設計上其實走入了誤區。因為雲端基礎設施本身就已經幫你處理好網頁伺服器的路由與請求了,再疊加一層網頁框架,只是無謂地疊床架屋、消耗效能與預算。
Virtual Private Server (VPS)
VPS(虛擬專屬伺服器)是網頁框架的主戰場。當你的架構延伸到這個層級時,才真正需要開始撰寫傳統意義上的網頁伺服器程式。
在現代雲端分層架構下,通常只有在以下特定情境,才需要引入 VPS:
- 長時間運行的任務:例如建立 WebSocket 連線、即時通訊或監控服務。
- 背景運作的大型程式:需要持續消耗 CPU / 記憶體進行大量運算、排程(Cron Job)或數據處理的後端服務。
- 管理與連接資料庫的程式:需要穩定、常駐型連線池(Connection Pool)來频繁存取資料庫的場景。
值得注意的是,在 FaaS 層級所寫的核心業務邏輯,到了 VPS 依然可以共用與複用,差別僅在於此時需要將它內嵌進特定的網頁框架中作為路由的處理函式。
此外,如果你想擁有 VPS 的常駐特性,卻不想花時間維護作業系統與基礎環境,傳統的 PaaS(平台即服務,如 Heroku、Render) 也是一個替代方案,缺點是維運預算會稍微高一些。
技術棧選型建議
在這個分層架構下,你只需要準備好以下核心技術:
JavaScript / TypeScript:無論架構如何演變,這兩者永遠是 Web 開發無可取代的核心。從 Frontend 的瀏覽器環境,到 Edge Function 的 V8 Isolate,甚至是 FaaS 與 VPS,JavaScript 都能完美貫穿全場。
選一種高效能的「編譯型語言」:為了在 FaaS 層級極大化降低運行成本,建議掌握一種編譯型語言。如果你覺得傳統的 C/C++ 開發門檻較高、不好撰寫,Golang 或 Rust 都是極佳的替代方案。
傳統的 Java 平台在 FaaS 環境中會比較吃虧,因為 JVM 的 Runtime 體積較大且冷啟動(Cold Start)時間較長,容易無謂地增加計費時間。
🚀 給開發者的實戰策略
當你準備將傳統代碼遷移到 FaaS 平台時,千萬不要急著一開始就用編譯型語言重新實作所有邏輯。
最佳的策略是:先沿用原本的 JavaScript/TypeScript 代碼,直接在 FaaS 上跑 Node.js 環境。 部署上線後觀察一段時間,如果雲端平台的帳單金額在可接受範圍內,就能直接省下重構與移植程式碼的時間成本。只有當特定函式引發高額計費時,才是引入 Golang 或 Rust 進行優化的時機。
回歸本質,讓基礎設施為你打工
從 CGI 時代到網頁框架的繁榮,再到如今 Frontend、Edge、FaaS、VPS 並存的多維度分層架構,網頁開發的本質其實從未改變——那就是高效率地交付業務價值。
過去,網頁框架幫我們包辦了路由、中介軟體和資料庫連接;而今天,雲端巨頭們的基礎設施(Infrastructure)已經進化到可以直接在網路邊緣、在極速的微型容器中,幫我們處理好網頁請求。
「不需要網頁框架」並不是要大家走回頭路去手寫 CGI,而是提醒現代開發者:學會精準地把代碼部署在最適合它的架構層級上。
善用科技巨頭的基礎設施,把疊床架屋的框架時間省下來,專注於真正的核心邏輯。這才是現代 Web 開發者最優雅、也最經濟的模式。