許多年輕的開發者或許很難想象,在單頁應用和 Node.js 尚未席卷一切的那個時代,Web 框架曾經真正“擁有”整個技術棧。數據庫的查詢抽象、模板的渲染邏輯、用戶輸入的校驗規則、會話的存儲機制,乃至最后部署到服務器的目標平臺,所有這些組件都在一個內聚的系統里被精心設計,彼此默契配合。開發者走進框架的文檔站,就能看清什么是官方推薦的做法,什么又處于地圖之外。當你習慣了這種感覺,再回頭看如今 JavaScript 生態里的全棧開發,那種割裂感就會格外清晰。Primate 的創始人正是帶著這種懷舊與不滿,開啟了一個新的框架項目,試圖重新拿回全棧框架對技術棧的所有權。
Primate 的作者回憶,自己早年幾乎是用 PHP 框架構筑了整個 Web 開發觀的。那會兒他主要用 Yii,偶爾也接觸 Laravel,但真正打動他的其實不是 PHP 這門語言本身,而是框架帶來的那種一體感。在那個世界里,數據庫訪問、模板、路由、校驗、MVC 的組織范式,全都裝在同一個“盒子”里。你當然可以替換掉其中的一些部件,比如換個模板引擎,或者接入不同的緩存驅動,但所有這些動作依然發生在一個高度協調的系統內部。框架的作者們已經替你考慮好了部件之間的交互邊界和約定,你哪怕不太清楚底層的連線,也輕易碰不到那些被稱為“接縫”的脆弱地帶。這種對全棧的完整所有權,在作者看來,是構建復雜 Web 應用時極為寶貴的設計特質。
當 JavaScript 從瀏覽器大舉進軍服務端之后,上述這種“框架擁有整個棧”的理念幾乎消失殆盡。Node.js 帶來的不僅是事件驅動和非阻塞 I/O,還有一種徹底奉行“組合優于內聚”的工程文化。開發者開始習慣這樣組裝自己的應用:先挑一個稱手的 HTTP 服務框架,再選一個數據庫客戶端,然后搭配單獨的校驗庫、單獨的會話管理庫、單獨的前端視圖層,最后再用打包工具和構建腳本把這一切粘合起來。這種哲學聽上去非常 UNIX:每個工具只做好一件事。然而,Web 應用遠不止是孤立工具的線性管道,它天然包含著大量需要共享的上下文。請求體的結構規范、校驗的邊界規則、會話的管理策略、渲染的入口約定、路由與序列化格式的映射、對應不同部署環境的適配邏輯——所有這些元信息本應在一個體系內被統一而自然地表達。現實卻是,問題常常就出在這些工具們碰面的“接縫”處,而且往往以極細微的方式暴露出來,讓人排查到深夜。
元框架(Meta-frameworks)的出現讓情形有所好轉,但這種改善方式,更像是在五花八門的身體上強行套入同一件緊身衣。Next.js 給出了一個高度一致的技術棧,但它本質上是一個 React 的技術棧。如果某天你發現了 Solid 的響應式優勢,想在自己的應用里嘗試一下,對不起,這不是在視圖層換個庫那么簡單。你沒法把 React 的視圖渲染輕輕撥到一邊,然后把 Solid 的組件樹接上去。你要做的,是整體遷移到另一個為 Solid 打造的元框架里去,而這個新框架會帶著一套不同的約定、不同的路由細節、不同的后端集成假設,甚至不同的數據獲取模式。同樣的事情在生態里反復上演:React 有一個元框架,Solid 有另一個,Svelte 有自己的,Vue 也有自己的。每個框架都在重新解決幾乎一樣的后端問題,但解決方式又都帶著點微妙的差異,逼著開發者每當想換個前端方案時,就必須重學一遍那些本不該成為負擔的東西。
運行時(Runtime)的碎片化讓局面雪上加霜。Node.js、Deno、Bun 都是具備生產力水準的 JavaScript 運行時,但如今一些框架已經實際上與特定的運行時綁定在了一起。這意味著你的應用不只是被鎖在一個前端庫里,還會被進一步鎖死在一個運行時上。即便某些框架宣稱自己“支持”Deno 或 Bun,這個“支持”的含義經常不過是該運行時剛好兼容 Node.js 的 API,能夠把為 Node 寫的代碼跑起來而已。這離“框架在設計上就充分利用了各個運行時的原生 API 和執行模型”還差得很遠。于是,當你試圖用 Deno 原生的 fetch 實現去替代某個 Node 特有的網絡庫時,往往會在框架約定和運行時的實際行為之間撞上一堵隱形的墻。
在 Primate 的作者看來,這種種綁定毫無必要。前端的本質就是一套描述瀏覽器用戶界面的方案,后端的本質是處理請求、數據和業務邏輯的模型,而運行時的本質則是代碼的執行目標平臺。這三者不應該被強制焊死在一個固定的組合里,它們天然就應該被允許獨立演化、自由搭配。你完全應當能夠用 React 寫出一個路由,用 Svelte 寫另一個,再用 Marko 寫完第三個,而整個后端模型、校驗邏輯和會話管理都不需要為此做出任何實質性改變。同理,寫后端路由的方式也不該被某個特定的元框架所壟斷,更不應隨著你選擇的前端庫不同而被迫重寫。
這種靈活性不是那種“理論上可以”的虛空許諾。Primate 的核心設計目標,恰恰就是把前端視圖層、后端業務層和底層運行時的選擇權,真正交還給開發者。它并不試圖成為又一個帶著自己強烈偏好的元框架,而是要扮演一種更高維度的粘合角色:在保留各組件獨立性與最佳實踐的前提下,提供一個讓它們能夠安然共處的溫層。當框架真正擁有全棧所有權,它提供的不是僵硬的捆綁,而是一套清晰規劃好的契約——讓你確切地知道,在哪些范圍內是你熟悉的領土,在哪些邊界之外你需要格外留神。這樣,你才不會在每個框架的文檔地獄里反復迷失,也才能在技術潮流更迭時,不被整套技術棧的遷徙成本拖垮。
回看歷史,PHP 全棧框架的遺產與其說是某個具體的技術方案,不如說是一種工程哲學:一個好的 Web 框架應當為你把各層之間的關聯都料理妥當,讓你可以專注于業務本身,而不是在粘合工具的泥潭里消耗心力。今天層不出窮的前端方案和運行時變局,反而讓這種哲學有了更現實的回歸理由。Primate 的出現,或許正提醒著社區:與其在每種前端技術后面都跟一套復雜的全棧家族,不如反過來思考,怎樣讓同一個堅實的后端世界,從容地掛載起多種多樣、并且可以隨時替換的視圖層。這種愿景聽起來過于理想化,但至少,已經有人開始認真地把它變成一行行能夠運行的代碼。而這,本身就是一個值得興奮的開始。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.