使用 Gatsby 函數構建 API
已發表: 2022-03-10您可能聽說過無服務器函數,但如果您沒有聽說過,無服務器函數提供通常與服務器端技術相關的功能,這些功能可以與前端代碼一起實現,而不會被服務器端基礎設施所束縛。
由於服務器端和客戶端代碼在同一個代碼庫中共存,像我這樣的前端開發人員可以使用他們已經熟悉和喜愛的工具擴展可能的範圍。
限制
共存很棒,但我遇到過至少兩種情況,以這種方式使用無服務器函數並不完全適合手頭的任務。 它們如下:
- 前端無法支持無服務器功能。
- 不止一個前端需要相同的功能。
為了幫助提供一些上下文,這裡是上面提到的第 1 點和第 2 點的一個示例。 我維護了一個名為 MDX Embed 的開源項目,您會從 docs 站點看到它不是 Gatsby 網站。 它是使用 Storybook 構建的,Storybook 本身不提供無服務器功能功能。 我想實現“支付你想要的”捐款來幫助資助這個項目,我想使用 Stripe 來實現安全支付,但如果沒有安全的“後端”,這是不可能的。
通過將此功能抽像到使用 Gatsby Functions 構建的 API 中,我能夠使用 MDX Embed 實現我想要的,並且還可以重用相同的功能並為我的博客啟用“按需付費”功能。
您可以在此處閱讀有關我如何做到這一點的更多信息:使用 Gatsby 函數和 Stripe 將開源軟件貨幣化。
正是在這一點上,使用 Gatsby Functions 可以充當前端或 BFF 的一種後端,以這種方式開發更類似於開發 API(應用程序編程接口)。
前端代碼使用 API 來處理諸如登錄、實時數據獲取或僅由瀏覽器無法適當處理的安全任務。 在本教程中,我將解釋如何使用 Gatsby Functions 構建 API 並將其部署到 Gatsby Cloud。
預檢檢查
Gatsby Functions 在部署到 Gatsby Cloud 或 Netlify 時工作,在本教程中,我將解釋如何部署到 Gatsby Cloud,因此您需要先註冊並創建一個免費帳戶。
您還需要一個 GitHub、GitLab 或 BitBucket 帳戶,這是 Gatsby Cloud 讀取您的代碼然後構建您的“站點”的方式,或者在本例中是 API。
出於本教程的目的,我將使用 GitHub。 如果您更願意繼續前進,可以在我的 GitHub 上找到完成的演示 API 代碼。
入門
在本地驅動器的某處創建一個新目錄,然後在終端中運行以下命令。 這將設置一個默認的package.json
。
npm init -y
依賴項
在終端中鍵入以下內容以安裝所需的依賴項。
npm install gatsby react react-dom
頁面
您的 API 可能沒有任何“頁面”,但為了避免在瀏覽器中訪問根 URL 時看到 Gatsby 的默認缺失頁面警告,請將以下內容添加到src/pages/index.js
和src/pages/404.js
。
//src/pages/index.js & src/pages/404.js export default () => null;
API
將以下內容添加到src/api/my-first-function.js
。
稍後我將解釋'Access-Control-Allow-Origin', '*'
含義,但簡而言之,它確保您的來自其他來源的 API 不會被 CORS 阻止。
//src/api/my-first-function.js export default function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.status(200).json({ message: 'A ok!' }); }
腳本
將以下內容添加到package.json
。
//package.json ... "scripts": { "develop": "gatsby develop", "build": "gatsby build" }, ...
啟動 Gatsby 開發服務器
要啟動 Gatsby 開發服務器,請在終端中運行以下命令。
npm run develop
從瀏覽器發出請求
隨著 Gatsby 的開發服務器運行,您可以訪問 http://localhost:8000/api/my-first-function,由於這是一個簡單的GET
請求,您應該在瀏覽器中看到以下內容。
{ "message": "A ok!" }
恭喜
您剛剛使用 Gatsby 函數開發了一個 API。
部署
如果您在瀏覽器中看到上述響應,則可以安全地假設您的函數在本地正常工作,在以下步驟中,我將解釋如何將您的 API 部署到 Gatsby Cloud 並使用來自 CodeSandbox 的HTTP
請求訪問它。
將代碼推送到 Git
在嘗試部署到 Gatsby Cloud 之前,您需要將代碼推送到您選擇的 Git 提供商。
蓋茨比雲
登錄到您的 Gatsby Cloud 帳戶並尋找顯示“添加站點 +”的紫色大按鈕。
在下一步中,您將被要求從 Git 存儲庫導入或從模板開始,選擇Import from Git Repository
並點擊next
。
如上所述,Gatsby Cloud 可以連接到 GitHub、GitLab 或 Bitbucket。 選擇您喜歡的 Git 提供程序並點擊next
。
連接您的 Git 提供程序後,您可以搜索您的存儲庫,並為您的站點命名。
一旦您選擇了您的存儲庫並將您的站點命名為next
。
您可以跳過“集成”和“設置”,因為我們不需要這些。
如果一切都按計劃進行,您應該會看到類似於以下屏幕截圖的內容。
您會在屏幕左側的頂部附近看到一個以gatsbyjs.io
結尾的 URL,這將是您的 API 的 URL,您創建的任何函數都可以通過添加/api/name-of-function
來訪問/api/name-of-function
到此 URL 的末尾。
例如,我的演示 API 的my-first-function.js
的完整部署版本如下:
演示 API:我的第一個函數。
測試你的 API
訪問 API 的 URL 是一回事,但這並不是 API 通常的使用方式。 理想情況下,要測試您的 API,您需要從完全不相關的來源向函數發出請求。
就在這裡res.setHeader('Access-Control-Allow-Origin', '*');
前來救援。 雖然允許任何域(網站)訪問您的功能並不總是可取的,但在大多數情況下,公共功能就是這樣,公共的。 將 Access Control 標頭設置為值*
意味著任何域都可以訪問您的函數,如果沒有這個,除了託管 API 的域之外的任何域都將被 CORS 阻止。
這是一個使用我的演示 API 中my-first-function
的 CodeSandbox。 您可以分叉並更改 Axios 請求 URL 以測試您的功能。
CodeSandbox:我的第一個函數
變得更漂亮
從您的 API 發送一條響應message: "A ok!"
不是很令人興奮,所以接下來我將向您展示如何查詢 GitHub REST API 並使用您剛剛創建的 API 製作個人資料卡以顯示在您自己的網站上,它看起來有點像這樣.
CodeSandbox:演示資料卡
依賴項
要使用 GitHub REST API,您需要安裝 @octokit/rest 包。
npm install @octokit/rest
獲取 GitHub 用戶原始數據
將以下內容添加到src/api/get-github-user-raw.js
。
// src/api/get-github-user-raw.js import { Octokit } from '@octokit/rest'; const octokit = new Octokit({ auth: process.env.OCTOKIT_PERSONAL_ACCESS_TOKEN }); export default async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); try { const { data } = await octokit.request(`GET /users/{username}`, { username: 'PaulieScanlon' }); res.status(200).json({ message: 'A ok!', user: data }); } catch (error) { res.status(500).json({ message: 'Error!' }); } }
訪問令牌
要與 GitHub REST API 通信,您需要一個訪問令牌。 您可以按照 GitHub 上的本指南中的步驟獲取此信息:創建個人訪問令牌。
.env
變量
為了保證您的訪問令牌安全,請將以下內容添加到.env.development
和.env.production
。
OCTOKIT_PERSONAL_ACCESS_TOKEN=123YourAccessTokenABC
您可以在 Gatsby 的本指南中閱讀有關 Gatsby 環境變量的更多信息:環境變量。
啟動開發服務器
正如您之前所做的那樣,通過在終端中鍵入以下內容來啟動 Gatsby 開發服務器。
npm run develop
從瀏覽器發出請求
隨著 Gatsby 開發服務器的運行,您可以訪問 http://localhost:8000/api/get-github-user-raw,由於這也是一個簡單的GET
請求,您應該在瀏覽器中看到以下內容。 (為簡潔起見,我刪除了部分回复。 )
{ "message": "A ok!", "user": { "login": "PaulieScanlon", "id": 1465706, "node_id": "MDQ6VXNlcjE0NjU3MDY=", "avatar_url": "https://avatars.githubusercontent.com/u/1465706?v=4", "gravatar_id": "", "url": "https://api.github.com/users/PaulieScanlon", "type": "User", "site_admin": false, "name": "Paul Scanlon", "company": "Paulie Scanlon Ltd.", "blog": "https://www.paulie.dev", "location": "Worthing", "email": "[email protected]", "hireable": true, "bio": "Jamstack Developer / Technical Content Writer (freelance)", "twitter_username": "pauliescanlon", "created_at": "2012-02-23T13:43:26Z", "two_factor_authentication": true, ... } }
這是完整原始響應的 CodeSandbox 示例。
CodeSandbox:原始響應
你會從上面看到,返回了很多我並不真正需要的數據,下一點完全取決於你,因為它是你的 API,但我發現稍微操作 GitHub API 響應很有幫助在將其發送回我的前端代碼之前。
如果你想做同樣的事情,你可以創建一個新函數並將以下內容添加到src/api/get-github-user.js
。
// src/api/get-github-user.js import { Octokit } from '@octokit/rest'; const octokit = new Octokit({ auth: process.env.OCTOKIT_PERSONAL_ACCESS_TOKEN }); export default async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); try { const { data } = await octokit.request(`GET /users/{username}`, { username: 'PaulieScanlon' }); res.status(200).json({ message: 'A ok!', user: { name: data.name, blog_url: data.blog, bio: data.bio, photo: data.avatar_url, githubUsername: `@${data.login}`, githubUrl: data.html_url, twitterUsername: `@${data.twitter_username}`, twitterUrl: `https://twitter.com/${data.twitter_username}` } }); } catch (error) { res.status(500).json({ message: 'Error!' }); } }
從上面你會看到,我沒有返回 GitHub REST API 返回的完整數據對象,而是只選擇我需要的位,重命名它們並在用戶名和 URL 值之前添加一些位。 當您在前端代碼中呈現數據時,這會讓生活變得更輕鬆。
這是格式化響應的 CodeSandbox 示例。
CodeSandbox:格式化響應
這與之前的 Profile Card CodeSandbox 非常相似,但我還將數據打印出來,這樣您就可以看到每個被操縱的數據項是如何使用的。
在這一點上值得注意的是,本教程中的所有四個 CodeSandbox 演示都使用了演示 API,而且它們都不是使用 Gatsby 構建的,也不是託管在 Gatsby Cloud 上的——太棒了!
Gatsby Cloud .env
變量
在部署兩個新函數之前,您需要將 GitHub 訪問令牌添加到 Gatsby Cloud 中的環境變量部分。
然後去哪兒?
我問自己這個問題。 通常來說,無服務器函數用於客戶端請求,雖然這很好,但我想知道它們是否也可以在構建時用於將數據靜態“烘焙”到頁面中,而不是依賴於可能會或可能不會在用戶中禁用的 JavaScript瀏覽器。
……所以這正是我所做的。
這是一種數據儀表板,它使用 Gatsby Functions 在運行和構建時返回的數據。 我使用 Astro 構建了這個站點並將其部署到 GitHub Pages。
我認為這是一個很好的方法的原因是因為我能夠在服務器和瀏覽器中重複使用相同的功能而無需複制任何內容。
在這個 Astro 構建中,我點擊了由我的 API 公開的相同端點以返回數據,然後這些數據要么被烘焙到頁面中(非常適合 SEO),要么在運行時由瀏覽器獲取(非常適合顯示新鮮或最新的實時數據) .
數據儀表板
網站左側顯示的數據是在構建時請求的,並使用 Astro 烘焙到頁面中。 頁面右側的數據是在運行時使用客戶端請求請求的。 我使用了由 GitHub REST API 公開的略有不同的端點來查詢創建不同列表的不同 GitHub 用戶帳戶。
你在這個網站上看到的一切都是由我更完整的 API 提供的。 我稱它為:Paulie API,我將它用於我的許多網站。
保利 API
Paulie API 與本教程中的 API 類似,是使用 Gatsby 構建的,但因為 Gatsby 既可以作為站點也可以作為 API,我使用它來記錄我的所有函數的工作方式,並且每個端點都有自己的頁面,可以用作交互式操場......隨意看看周圍。
所以,你有它,可以被任何客戶端或服務器端代碼使用的 Gatsby 函數 API,來自任何使用任何技術堆棧構建的網站。
試一試,我很想看看你建立了什麼。 隨時在下面的評論中分享或在 Twitter 上找到我:@PaulieScanlon。