Budowanie API z funkcjami Gatsby
Opublikowany: 2022-03-10Prawdopodobnie słyszałeś o funkcjach bezserwerowych, ale jeśli nie, funkcje bezserwerowe zapewniają funkcje zwykle związane z technologiami po stronie serwera, które można zaimplementować wraz z kodem frontonu bez wpadania w pułapkę infrastruktury po stronie serwera.
Dzięki współistnieniu kodu po stronie serwera i po stronie klienta w tej samej bazie kodu, programiści front-end, tacy jak ja, mogą rozszerzyć zasięg tego, co jest możliwe, korzystając z narzędzi, które już znają i kochają.
Ograniczenia
Koegzystencja jest świetna, ale istnieją co najmniej dwa scenariusze, które napotkałem, w których użycie funkcji bezserwerowych w ten sposób nie było odpowiednie dla danego zadania. Są to:
- Interfejs nie obsługuje funkcji bezserwerowych.
- Ta sama funkcjonalność była wymagana przez więcej niż jeden interfejs.
Aby pomóc w przedstawieniu kontekstu, podajemy jeden przykład obu punktów 1 i 2 wymienionych powyżej. Utrzymuję projekt Open-source o nazwie MDX Embed, na stronie z dokumentacją zobaczysz, że nie jest to witryna Gatsby. Został zbudowany przy użyciu samych Storybook i Storybook, które nie zapewniają żadnych funkcji bezserwerowych. Chciałem wdrożyć składki „Płać, co chcesz”, aby pomóc w finansowaniu tego projektu i chciałem użyć Stripe, aby umożliwić bezpieczne płatności, ale bez bezpiecznego „zaplecza”. Nie byłoby to możliwe.
Abstrahując tę funkcjonalność w API zbudowanym z Gatsby Functions, udało mi się osiągnąć to, czego chciałem dzięki MDX Embed, a także ponownie wykorzystać tę samą funkcjonalność i włączyć funkcję „Płać ile chcesz” na moim blogu.
Możesz przeczytać więcej o tym, jak to zrobiłem, tutaj: Zarabiaj na oprogramowaniu Open Source z funkcjami Gatsby i paskiem.
W tym momencie używanie Gatsby Functions może działać jako rodzaj zaplecza dla frontendu lub BFF, a programowanie w ten sposób jest bardziej zbliżone do tworzenia API (interfejsu programowania aplikacji ).
Interfejsy API są używane przez kod frontonu do obsługi takich rzeczy, jak logowanie, pobieranie danych w czasie rzeczywistym lub bezpieczne zadania, które nie są odpowiednio obsługiwane przez samą przeglądarkę. W tym samouczku wyjaśnię, jak zbudować interfejs API za pomocą Gatsby Functions i wdrożyć go w Gatsby Cloud.
Kontrole przed lotem
Funkcje Gatsby działają po wdrożeniu w Gatsby Cloud lub Netlify, a w tym samouczku wyjaśnię, jak wdrożyć w Gatsby Cloud, więc najpierw musisz się zarejestrować i utworzyć bezpłatne konto.
Będziesz także potrzebował konta GitHub, GitLab lub BitBucket, w ten sposób Gatsby Cloud odczytuje Twój kod, a następnie buduje Twoją „stronę” lub w tym przypadku API.
Na potrzeby tego samouczka będę korzystał z usługi GitHub. Jeśli wolisz iść do przodu, gotowy kod API demonstracyjnego można znaleźć na moim GitHub.
Pierwsze kroki
Utwórz nowy katalog gdzieś na dysku lokalnym i uruchom następujące w swoim terminalu. Spowoduje to skonfigurowanie domyślnego package.json
.
npm init -y
Zależności
Wpisz następujące polecenie w swoim terminalu, aby zainstalować wymagane zależności.
npm install gatsby react react-dom
Strony
Prawdopodobnie Twój interfejs API nie będzie zawierał żadnych „stron”, ale aby uniknąć wyświetlania ostrzeżenia Gatsby o domyślnej brakującej stronie podczas odwiedzania głównego adresu URL w przeglądarce, dodaj następujące elementy zarówno do src/pages/index.js
, jak i src/pages/404.js
.
//src/pages/index.js & src/pages/404.js export default () => null;
API
Dodaj następujące elementy do src/api/my-first-function.js
.
Wyjaśnię nieco później, co oznacza 'Access-Control-Allow-Origin', '*'
, ale krótko mówiąc, zapewnia to, że Twoje interfejsy API z innych źródeł nie są blokowane przez 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!' }); }
Skrypty
Dodaj następujące elementy do package.json
.
//package.json ... "scripts": { "develop": "gatsby develop", "build": "gatsby build" }, ...
Uruchom serwer programistyczny Gatsby
Aby uruchomić serwer programistyczny Gatsby, uruchom w terminalu następujące elementy.
npm run develop
Złóż wniosek z przeglądarki
Z uruchomionym serwerem programistycznym Gatsby'ego możesz odwiedzić http://localhost:8000/api/my-first-function, a ponieważ jest to proste żądanie GET
, powinieneś zobaczyć następujące informacje w swojej przeglądarce.
{ "message": "A ok!" }
Gratulacje
Właśnie opracowałeś interfejs API przy użyciu funkcji Gatsby.
Wdrożyć
Jeśli widzisz powyższą odpowiedź w swojej przeglądarce, możesz bezpiecznie założyć, że Twoja funkcja działa poprawnie lokalnie, w poniższych krokach wyjaśnię, jak wdrożyć API w Gatsby Cloud i uzyskać do niego dostęp za pomocą żądania HTTP
z CodeSandbox.
Prześlij kod do Gita
Przed przystąpieniem do wdrożenia w Gatsby Cloud musisz przekazać swój kod wybranemu dostawcy Git.
Chmura Gatsby'ego
Zaloguj się na swoje konto Gatsby Cloud i poszukaj dużego fioletowego przycisku z napisem „Dodaj witrynę +”.
W następnym kroku zostaniesz poproszony o Importuj z repozytorium Git lub Rozpocznij od szablonu, wybierz Import from Git Repository
i kliknij next
.
Jak wspomniano powyżej, Gatsby Cloud może łączyć się z GitHub, GitLab lub Bitbucket. Wybierz preferowanego dostawcę Git i kliknij next
.
Po połączeniu się z dostawcą Git możesz wyszukać swoje repozytorium i nadać swojej witrynie nazwę.
Po wybraniu repozytorium i nazwaniu witryny kliknij przycisk next
.
Możesz pominąć „Integracje” i „Konfigurację”, ponieważ nie będziemy ich potrzebować.
Jeśli wszystko poszło zgodnie z planem, powinieneś zobaczyć coś podobnego do poniższego zrzutu ekranu.
U góry po lewej stronie ekranu zobaczysz adres URL kończący się na gatsbyjs.io
, będzie to adres URL Twojego interfejsu API, a dostęp do wszystkich tworzonych funkcji można uzyskać, dodając /api/name-of-function
na końcu tego adresu URL.
Na przykład kompletna wdrożona wersja my-first-function.js
dla mojego demo API wygląda następująco:
Demo API: Moja pierwsza funkcja .
Testowanie Twojego API
Odwiedzenie adresu URL Twojego interfejsu API to jedno, ale tak naprawdę nie jest to sposób, w jaki interfejsy API są zwykle używane. Idealnie, aby przetestować swoje API, musisz wykonać żądanie do funkcji z zupełnie niepowiązanego źródła.
To tutaj res.setHeader('Access-Control-Allow-Origin', '*');
przychodzi na ratunek. Chociaż nie zawsze jest pożądane zezwolenie dowolnej domenie (witrynie) na dostęp do twoich funkcji, w większości funkcje publiczne są po prostu publiczne. Ustawienie nagłówka Access Control na wartość *
oznacza, że każda domena może uzyskać dostęp do Twojej funkcji, bez tego każda domena inna niż domena, w której jest hostowany interfejs API, zostanie zablokowana przez CORS.
Oto CodeSandbox, który używa my-first-function
z mojego demo API. Możesz to rozwidlić i zmienić adres URL żądania Axios, aby przetestować swoją funkcję.
CodeSandbox: Moja pierwsza funkcja
Stawanie się hodowcą
Wysyłanie odpowiedzi z Twojego interfejsu API, która zawiera message: "A ok!"
nie jest dokładnie ekscytujące, więc w następnym fragmencie pokażę Ci, jak wykonać zapytanie do interfejsu API GitHub REST i utworzyć osobistą kartę profilu, która będzie wyświetlana we własnej witrynie za pomocą właśnie utworzonego interfejsu API, i będzie to wyglądać trochę tak .
CodeSandbox: Karta profilu demonstracyjnego
Zależności
Aby korzystać z GitHub REST API, musisz zainstalować pakiet @octokit/rest.
npm install @octokit/rest
Pobierz surowe dane użytkownika GitHub
Dodaj następujące elementy do 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!' }); } }
Token dostępu
Aby komunikować się z GitHub REST API, potrzebujesz tokena dostępu. Możesz to uzyskać, wykonując kroki opisane w tym przewodniku z GitHub: Tworzenie osobistego tokena dostępu.
.env
Zmienne
Aby zapewnić bezpieczeństwo tokena dostępu, dodaj następujące elementy do .env.development
i .env.production
.
OCTOKIT_PERSONAL_ACCESS_TOKEN=123YourAccessTokenABC
Możesz przeczytać więcej o zmiennych środowiskowych Gatsby w tym przewodniku z Gatsby: Zmienne środowiskowe.
Uruchom serwer programistyczny
Tak jak wcześniej, uruchom serwer programistyczny Gatsby, wpisując w terminalu następujące polecenie.
npm run develop
Złóż wniosek z przeglądarki
Z uruchomionym serwerem programistycznym Gatsby możesz odwiedzić http://localhost:8000/api/get-github-user-raw, a ponieważ jest to również proste żądanie GET
, powinieneś zobaczyć następujące informacje w swojej przeglądarce. ( Usunąłem część odpowiedzi dla zwięzłości. )
{ "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, ... } }
Oto przykład pełnej surowej odpowiedzi w CodeSandbox.
CodeSandbox: surowa odpowiedź
Z powyższego zobaczysz, że zwracanych jest sporo danych, których tak naprawdę nie potrzebuję, ten następny bit zależy wyłącznie od Ciebie, ponieważ jest to Twoje API, ale uznałem za pomocne trochę manipulować odpowiedzią API GitHub przed odesłaniem go z powrotem do mojego kodu frontendowego.
Jeśli chcesz zrobić to samo, możesz utworzyć nową funkcję i dodać następujące elementy do 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!' }); } }
Z powyższego zobaczysz, że zamiast zwracać kompletny obiekt danych zwrócony przez interfejs API GitHub REST, wybieram tylko potrzebne mi bity, zmieniam ich nazwy i dodaję kilka bitów przed wartościami nazwy użytkownika i adresu URL. Ułatwia to nieco życie, gdy przychodzisz do renderowania danych w kodzie frontendowym.
Oto przykład CodeSandbox sformatowanej odpowiedzi.
CodeSandbox: Sformatowana odpowiedź
Jest to bardzo podobne do wcześniejszej karty Profile Card CodeSandbox, ale wydrukowałem również dane, abyś mógł zobaczyć, jak używany jest każdy zmanipulowany element danych.
Warto w tym miejscu zauważyć, że wszystkie cztery dema CodeSandbox w tym samouczku korzystają z demonstracyjnego interfejsu API i żadna z nich nie jest zbudowana przy użyciu Gatsby ani hostowana na Gatsby Cloud — super!
Zmienne .env
w chmurze Gatsby
Przed wdrożeniem dwóch nowych funkcji musisz dodać token dostępu GitHub do sekcji zmiennych środowiskowych w Gatsby Cloud.
Gdzie iść stąd?
Zadałem sobie to pytanie. Zazwyczaj funkcje bezserwerowe są używane w żądaniach po stronie klienta i chociaż jest to w porządku, zastanawiałem się, czy można ich również użyć w czasie kompilacji do statycznego „pieczenia” danych na stronie, zamiast polegać na JavaScript, który może lub nie może być wyłączony w przeglądarka.
…więc dokładnie to zrobiłem.
Oto rodzaj pulpitu nawigacyjnego danych, który wykorzystuje dane zwracane przez funkcje Gatsby zarówno w czasie wykonywania, jak i kompilacji. Zbudowałem tę witrynę za pomocą Astro i wdrożyłem ją na GitHub Pages.
Powodem, dla którego uważam, że jest to świetne podejście, jest to, że jestem w stanie ponownie wykorzystać tę samą funkcjonalność zarówno na serwerze, jak iw przeglądarce, bez duplikowania czegokolwiek.
W tej kompilacji Astro trafiłem na ten sam punkt końcowy, który został udostępniony przez moje API, aby zwrócić dane, które są następnie albo wypiekane na stronie (idealne dla SEO) lub pobierane w czasie wykonywania przez przeglądarkę (idealne do pokazywania świeżych lub najświeższych danych na żywo) .
Panel danych
Dane wyświetlane po lewej stronie są wymagane w czasie kompilacji i umieszczane na stronie za pomocą Astro. Dane po prawej stronie są żądane w czasie wykonywania przy użyciu żądania po stronie klienta. Użyłem nieco innych punktów końcowych udostępnianych przez interfejs API GitHub REST do wysyłania zapytań do różnych kont użytkowników GitHub, które tworzą różne listy.
Wszystko, co widzisz na tej stronie, jest dostarczane przez moje bardziej kompletne API. Nazwałem to: Paulie API i używam go na wielu moich stronach internetowych.
Paulie API
Paulie API, podobnie jak API z tego samouczka, jest zbudowany z Gatsby, ale ponieważ Gatsby może działać zarówno jako witryna, jak i API, użyłem go do udokumentowania działania wszystkich moich funkcji, a każdy punkt końcowy ma własną stronę, która może być używana jako interaktywna plac zabaw… śmiało się rozejrzyj.
A więc masz to, API Gatsby Functions, z którego może korzystać dowolny kod po stronie klienta lub serwera, z dowolnej witryny internetowej zbudowanej z dowolnym stosem technologicznym.
Daj temu szansę, a byłbym bardzo zainteresowany, aby zobaczyć, co zbudujesz. Zapraszam do dzielenia się w komentarzach poniżej lub znajdź mnie na Twitterze: @PaulieScanlon.