Web 開發人員,您好!去年,我們發佈了一系列改進功能,簡化了在 Cloudflare 上部署 Web 應用程式的過程,如今,我們看到 Astro、Next.js、Nuxt、Qwik、Remix、SolidStart、SvelteKit 以及 Cloudflare 上代管的其他 Web 應用程式出現了大幅成長。今天,我們宣佈對與這些 Web 框架的整合進行重大改進,從而更輕鬆地使用我們的 D1 SQL 資料庫、R2 物件存放區、AI 模型以及 Cloudflare 開發人員平台的其他強大功能開發複雜的應用程式。
過去,如果您想使用 D1 開發一個由 Web 架構支援的應用程式並在本地執行,必須建置應用程式的生產版本,然後使用 `wrangler pages dev` 在本地執行它。雖然這很有效,但您的每次程式碼反覆運算都需要幾秒鐘,大型應用程式甚至需要幾十秒。使用生產版本進行反覆實在是太慢了,會讓您脫離流程,並且無法利用架構作者付出大量努力實現的所有開發體驗最佳化。這種情況在今天發生了改變!
我們的目標是以盡可能最自然的方式與 Web 架構整合,讓開發人員在將應用程式部署到 Cloudflare 時,無需學習和適應重大的工作流程變更或自訂 API。無論您是 Next.js 開發人員、Nuxt 開發人員,還是更喜歡其他架構,現在您都可以繼續使用熟悉的超快本機開發工作流程,並在 Cloudflare 上發佈您的應用程式。
所有完整堆疊 Web 架構都附帶一個為架構量身定製的本地開發伺服器,通常可提供出色的開發體驗,只有一個例外——它們不原生支援 Cloudflare 開發平台的一些重要功能,尤其是我們的儲存解決方案。
因此,直到最近,開發人員都不得不做出艱難的選擇。要麼使用特定於架構的開發伺服器來開發應用程式,但放棄使用 Cloudflare 的許多功能。要麼可以充分利用 Cloudflare 的平台,包括 D1 或 R2 等各種資源,但卻不得不放棄使用特定於架構的開發人員工具。在這種情況下,開發人員的反覆週期會減慢,而且需要幾秒鐘的時間才能在瀏覽器中看到程式碼變更的結果,而不是幾毫秒。但從今天開始,您無需再面臨此問題!讓我們來看看具體情況。
我們來構建一個應用程式
讓我們使用 C3(我們的 create-cloudflare CLI)建立一個新的應用程式。我們可以使用任何 npm 用戶端(有人使用 pnpm 嗎?),但為簡單起見,在本文中,我們將始終使用預設的 npm 用戶端。若要開始,只需執行:
$ npm create cloudflare@latest
為 App 提供一個名稱,或使用隨機產生的名稱。然後選擇 [網站或 Web App] 類別,並選擇心儀的完整堆疊架構。我們支援許多架構:Astro、Next.js、Nuxt、Qwik、Remix、SolidStart 和 SvelteKit。
由於 C3 將應用程式基架委託給最新版本的架構特定 CLI,因此您將完全按照架構作者的預期為應用程式構建基架,而不會錯過任何架構功能或選項。然後,C3 會向您的應用程式新增整合和部署到 Cloudflare 所需的一切,這樣您就無需自行設定。
為應用程式構建基架後,只需幾個步驟即可使其顯示資料庫中儲存的產品清單。首先,我們將資料庫的設定新增到我們的 wrangler.toml 設定檔案中:
[[d1_databases]]
binding = "DB"
database_name = "blog-products-db"
database_id = "XXXXXXXXXXXXXXXX"
是的,沒錯!現在,您可以透過 wrangler.toml 檔案設定您的繫結資源,即使對於部署到 Pages 的完整堆疊應用程式也是如此。我們將在專門的公告中分享有關 Pages 設定增強的更多資訊。
現在讓我們建立一個簡單的 schema.sql 檔案來代表我們的資料庫結構描述:
CREATE TABLE products(product_id INTEGER PRIMARY KEY, name TEXT, price INTEGER);
INSERT INTO products (product_id, name, price) VALUES (1, 'Apple', 250), (2, 'Banana', 100), (3, 'Cherry', 375);
並初始化我們的資料庫:
$ npx wrangler d1 execute blog-products-db --local --file schema.sql
請注意,我們使用了 wrangler d1 execute
的 –local
標誌來將變更套用至我們的本機 D1 資料庫。這是我們的開發伺服器將連線的資料庫。
接下來,如果您使用 TypeScript,請執行以下命令讓 TypeScript 瞭解您的資料庫:
$ npm run build-cf-types
此命令已針對透過 C3 建立的所有完整堆疊應用程式進行預先設定,並執行 wrangler types
以更新包含所有已設定繫結的 Cloudflare 環境介面。
現在,我們可以透過一個方便的捷徑來啟動架構提供的開發伺服器:
$ npm run dev
此捷徑將啟動您的架構的開發伺服器,無論其是由 next dev、nitro 還是 vite 提供支援。
現在,為了存取我們的資料庫並列出產品,我們可以使用特定於架構的方法。例如,在使用 App 路由器的 Next.js 應用程式中,我們可以使用以下內容更新 app/api/hello/route.ts
:
const db = getRequestContext().env.DB;
const productsResults = await db.prepare('SELECT * FROM products').all();
return Response.json(productsResults.results);
或者在 Nuxt 應用程式中,我們可以建立一個 server/api/hello.ts
檔案,並在其中填入:
export default defineEventHandler(async ({ context }) => {
const db = context.cloudflare.env.DB;
const productsResults = await db.prepare('SELECT * FROM products').all();
return productsResults.results;
});
假設架構開發伺服器在連接埠 3000 上執行,您可以導覽至 http://localhost:3000/api/hello,在任一架構中測試新的 API 路由。為簡單起見,我們在這些範例中選擇了 API 路由,但這也適用於任何 UI 產生路由。
每個 Web 架構都有自己的方式來定義路由並在整個應用程式中傳遞有關請求的上下文資訊,因此您存取資料庫、物件存放區和其他資源的方式將取決於您的架構。您可以閱讀我們更新的完整堆疊架構指南以瞭解更多資訊:
現在您已經知道如何在所選架構中存取 Cloudflare 的資源,您所熟知的其他架構相關資訊都保持不變。現在,您可以使用針對您的架構進行最佳化的開發伺服器在本地開發應用程式,這通常包括對熱模組替換 (HMR) 的支援、自訂開發工具、增強的偵錯支援等,同時仍然受益於 Cloudflare 特定的 API 和功能。這是一個雙贏的結果!
為了實現這些開發工作流程,實際發生了什麼變化?
為了減少開發延遲並保留特定於自訂架構的體驗,我們需要使 Web 架構及其開發伺服器能夠以無縫、幾乎不可見的方式與 wrangler 和 miniflare 整合。
Miniflare 是解決這個難題的關鍵元件。這是針對 Cloudflare 特定資源的本機模擬程式,由我們的 JavaScript (JS) 執行階段 workerd 提供支援。透過依賴 workerd,我們確保 Cloudflare 的 JavaScript API 以忠實模擬我們生產環境的方式在本地執行。問題在於,架構開發伺服器已經依賴 Node.js 來執行應用程式,因此將另一個 JS 執行階段加入其中,會破壞有關如何構建這些開發伺服器的許多假設。
然而,我們的團隊想出了一種有趣的方法來彌合這兩個 JS 執行階段之間的差距。我們稱之為 getPlatformProxy() API,它現在是 wrangler 的一部分,並由 miniflare 的 magic proxy 提供超級支援。此 API 公開一個 JS 代理物件,其行為就像包含所有繫結資源的尋常 Workers env 物件一樣。代理物件可讓 Node.js 中的程式碼透明地叫用在 workerd 中執行的 JavaScript 程式碼,以及存取特定於 Cloudflare 的執行階段 API。
有了 Node.js 和 workerd 執行階段之間的這座橋樑,您的應用程式現在可以在由 Node.js 提供支援的開發伺服器中執行時,直接存取 D1、R2、KV 和其他儲存解決方案的 Cloudflare 模擬程式。或者,您甚至可以編寫一個 Node.js 指令碼來執行相同的操作:
import {getPlatformProxy} from 'wrangler';
const {env} = getPlatformProxy();
console.dir(env);
const db = env.DB;
// Now let’s execute a DB query that runs in a local D1 db
// powered by miniflare/workerd and access the result from Node.js
const productsResults = await db.prepare('SELECT * FROM products').all();
console.log(productsResults.results);
在 getPlatformProxy()
API 可供使用的情況下,剩下的工作就是更新所有架構配接器、外掛程式,在某些情況下還包括架構本身,以利用此 API。我們非常感謝在此過程中從架構團隊獲得的支援,特別是來自 Astro 的 Alex、來自 Nuxt 的 pi0、來自 Remix 的 Pedro、來自 Solid 的 Ryan、來自 Svelte 的 Ben 和 Rich,以及 next-on-pages 專案中的協作者 James Anderson。
使用 Vite 對開發工作流程的未來改進
雖然 getPlatformProxy()
API 對於許多場景來說都是一個很好的解決方案,但我們還可以做得更好。如果可以在 JS 執行階段而不是 Node.js 中執行整個應用程式,我們就可以更忠實地模擬生產環境,並減少開發人員的摩擦和生產意外。
理想情況下,我們希望您針對部署到生產環境的相同執行階段進行開發,這只能透過將 workerd 直接整合到所有架構的開發伺服器中來實現,考慮到現有架構的數量以及它們之間的差異,這並不是一個簡單的工作。
不過,我們還算幸運。當我們開始這項工作時,我們很快意識到 Vite(一種被許多完整堆疊架構使用的流行開發伺服器)正在獲得越來越多的採用。事實上,Remix 最近才切換到 Vite,證實了 Vite 作為當今 Web 開發通用基礎的受歡迎程度。
如果 Vite 能夠為在替代 JavaScript 執行階段中執行完整堆疊應用程式提供一流的支援,我們就可以讓任何使用 Vite 的人在本地開發他們的應用程式,並且可以完全存取 Cloudflare 開發人員平台。不再有特定於架構的自訂整合和應變措施——完整堆疊架構的所有功能、Vite 和 Cloudflare 都可供所有開發人員使用。
聽起來好得令人難以置信?也許吧。我們很高興能與 Vite 團隊就 Vite 環境提案進行合作,該提案將推動實現上述目標。該提案仍在不斷改進中,敬請關注更新。
您今天將構建什麼內容?
我們的目標是讓 Cloudflare 成為 Web 開發人員的最佳開發平台。使用您已經熟悉的架構和工具快速輕鬆地開發應用程式是這一目標的重要組成部分。只需執行一個命令即可開始您的旅程:
$ npm create cloudflare@latest