Front End: Używanie Gatsby.js i Node.js do statycznych aktualizacji witryn
Opublikowany: 2022-03-11W przypadku niektórych wymagań projektowych statyczne generowanie stron jest nie tylko wystarczające , ale jest również najbardziej wydajne pod względem szybkości i skalowalności.
W pierwszej połowie tej serii połączyliśmy Node.js, Express, MongoDB, cron i Heroku, aby dostarczyć gotowy do CI backend, który wykorzystuje API GitHub zgodnie z dziennym harmonogramem. Teraz jesteśmy gotowi, aby dodać Gatsby'ego do miksu, aby ukończyć nasz projekt generowania statycznej strony.
Tworzenie interfejsu: zrób z niego witrynę Gatsby
Ponieważ witryny Gatsby są oparte na React, przydatne jest, jeśli wiesz już, jak zbudować witrynę internetową za pomocą Reacta.
Do stylizacji preferowałem Bootstrap, Reactstrap i React-Markdown. Być może wiesz, że informacje o wydaniu w GitHub są przechowywane w formacie Markdown, dlatego potrzebujemy konwertera.
Statyczna struktura projektu strony internetowej
Nasza struktura plików/folderów będzie następująca:
Do czego służą te pliki? Zobaczmy:
-
env.development
ienv.production
to pliki konfiguracyjne zmiennych środowiskowych. - Szablon
all-repositories.js
zostanie użyty na naszej stronie głównej, zawierającej listę repozytoriów. - Szablon
repository.js
posłuży do pokazania szczegółów dla danego repozytorium. -
gatsby-node.js
to miejsce, w którym wykorzystujemy nasz punkt końcowy zaplecza i uruchamiamy nasze metodycreatePage
. -
package.json
jak zawsze zawiera zależności i właściwości projektu. -
global.css
to nasz główny plik arkusza stylów.
Wdrożenie strony internetowej Gatsby
Podobnie jak w przypadku naszego zaplecza, uruchom npm install
(lub yarn
, jeśli masz zainstalowany Yarn) po dodaniu wymaganych zależności do package.json
interfejsu użytkownika:
{ // ... "dependencies": { "axios": "^0.18.0", "bootstrap": "^4.3.1", "gatsby": "^2.0.0", "react": "^16.5.1", "react-dom": "^16.5.1", "react-markdown": "^4.0.6", "reactstrap": "^7.1.0" } // ... }
env.development
i env.production
mają tylko adresy URL zaplecza dla odpowiednich środowisk. Ten pierwszy ma:
API_URL=http://localhost:3000
…podczas gdy produkcja ma:
API_URL=https://[YOUR_UNIQUE_APP_NAME].herokuapp.com
gatsby-node.js
zostanie uruchomiony tylko raz podczas tworzenia kodu. Dlatego musimy zebrać tutaj wszystkie niezbędne informacje z naszego zaplecza. Następnie odpowiedź zostanie wykorzystana z naszymi szablonami do wygenerowania odpowiednich stron statycznych.
W naszym przypadku all-repositories.js
potrzebuje wszystkich repozytoriów, a repository.js
potrzebuje odpowiedniego repozytorium dla każdej iteracji. Na koniec możemy dynamicznie generować ścieżki do stron, przekazując owner
repozytorium i parametry name
jako część pola path
:
const axios = require('axios'); require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` }); const getRepositoryData = async () => { console.log(process.env.API_URL); return axios.get(`${process.env.API_URL}/repositories`); }; exports.createPages = async ({ actions: { createPage } }) => { let repositories = await getRepositoryData(); repositories = repositories.data; // Create a page that lists all repositories. createPage({ path: `/`, component: require.resolve('./src/templates/all-repositories.js'), context: { repositories } }); // Create a page for each repository. repositories.forEach(repository => { createPage({ path: `/repository/${repository.owner}/${repository.name}`, component: require.resolve('./src/templates/repository.js'), context: { repository } }); }); };
W przypadku all-repositories.js
i repository.js
, jeśli pominiemy stylowanie, po prostu zbieramy dane z pageContext
i używamy ich tak, jak używamy parametrów w React.
W all-repositories.js
użyjemy pola repositories
pageContext
w następujący sposób:
export default ({pageContext: {repositories}}) => ( // ... <ListGroup> {/* Because the repositories parameter is a list, we are iterating over all items and using their fields */} {repositories.map(repository => (repository.tagName && <ListGroupItem className="repository-list-item"> // ... <Row> {`${repository.repositoryDescription}`} </Row> // ... </ListGroupItem> ))} </ListGroup> // ... );
Jeśli chodzi o repository.js
, zamiast tego użyjemy pola repository
pageContext
:
export default ({pageContext: {repository}}) => ( <div className="layout"> {repository.tagName && <ListGroupItem className="repository-list-item"> // ... <h1 className="release-notes">{`Release notes`}</h1> <hr/> {/* This the place where we will use Markdown-formatted release notes */} <ReactMarkdown source={`${repository.releaseDescription}`}/> </ListGroupItem> } // ... </div> );
Teraz upewnij się, że Twój backend jest gotowy do pracy. Przypomnij sobie, że dla tego projektu ustawiliśmy go jako http://localhost:3000.
Następnie uruchom program gatsby develop
z katalogu głównego projektu front-end i otwórz http://localhost:8000.
Jeśli dodałeś kilka repozytoriów (właściciel/nazwa) do swojego zaplecza i przynajmniej raz uruchomiłeś funkcję aktualizacji przez GitHub-API, powinieneś zobaczyć coś takiego:
A po kliknięciu jednego z repozytoriów powinieneś zobaczyć coś takiego:
Po powyższych zmianach nasza implementacja front-endowa jest zakończona.
Świetnie! Teraz musimy tylko wdrożyć.
Wdrażanie interfejsu
W tej części nie musimy wprowadzać żadnych zmian w naszej aplikacji front-endowej. Po prostu wdrożymy go do Netlify — będziesz potrzebować tam konta.
Ale najpierw musimy wdrożyć nasz kod w GitHub, GitLab lub Bitbucket. Podobnie jak w przypadku zaplecza, wdrożyłem swój kod na GitHub.
Następnie zaloguj się do Netlify i kliknij przycisk „Nowa witryna z Git” na pulpicie nawigacyjnym. Postępuj zgodnie z instrukcjami wyświetlanymi na ekranie, aby wybrać dostawcę Git i znaleźć swoje repozytorium.
W ostatnim kroku, jeśli poprawnie ustrukturyzowałeś kod, Netlify automatycznie ustawi polecenie budowania i opublikuje katalog poprawnie w następujący sposób:

Następnie kliknij „Wdróż witrynę”. Wdroży twoją witrynę w losowo wygenerowanej subdomenie Netlify, ale możesz to zmienić w dowolnym momencie — zmieniłem moje wdrożenie na https://sample-create-page-api-gatsby.netlify.com, gdzie możesz znaleźć demo na żywo ukończonej aplikacji.
Na razie w porządku. Ale ponieważ jest to statyczna aplikacja strony, musimy ją codziennie przebudowywać, aby była aktualna.
Codzienna aktualizacja za pomocą haka do budowania
Build hooks w Netlify działają jako wyzwalacze kompilacji, więc możesz je wyzwolić ze swojego zaplecza po zakończeniu zadania cron. Aby to zrobić, najpierw utwórz hak do budowania w Netlify.
W sekcji „Buduj i wdrażaj → Ciągłe wdrażanie” możesz znaleźć „Buduj haki”. Kliknij „Dodaj hak kompilacji”.
Nadaj mu nazwę i zapisz. (Nazwałem mine build-from-backend
.) Następnie skopiuj link, który generuje.
Teraz otwórzmy nasz projekt zaplecza i dodajmy te kilka linijek do pliku cron.controller.js
. Po prostu wysyłamy żądanie POST
na adres URL build-hook Netlify.
const Axios = require('axios'); const Config = require('../config/env.config'); const NETLIFY_BUILD_HOOK_URI = Config.netlifyEndpoint; function updateGatsby() { if (NETLIFY_BUILD_HOOK_URI) { console.log('Gatsby build request will be send'); Axios.post(NETLIFY_BUILD_HOOK_URI).then(() => { console.log('Gatsby build request was successful'); }); } }
Następnie zaktualizuj naszą funkcję updateDaily
:
function updateDaily() { RepositoryController.updateRepositories().then(() => { updateGatsby(); }); }
Na koniec zaktualizuj nasz plik env.config.js
, aby ustawić właściwość netlifyEndpoint
, która ma być zbierana ze zmiennych środowiskowych:
"netlifyEndpoint": process.env.NETLIFY_BUILD_HOOK || ""
Teraz musisz ustawić zmienną środowiskową NETLIFY_BUILD_HOOK
, którą przed chwilą skopiowałeś z Netlify. W Heroku możesz ustawić zmienne środowiskowe z sekcji „ustawienia” twojej aplikacji.
Po wypchnięciu zatwierdzenia, aplikacja zaplecza wyśle żądanie kompilacji do Netlify, a Twoje strony będą aktualizowane codziennie, pod koniec zadania cron. Oto, jak powinno wyglądać repozytorium po dodaniu funkcji przechwycenia kompilacji, wraz z ostatecznymi wersjami repozytorium zaplecza i repozytorium frontonu.
Na zakończenie projektu pokażemy, jak korzystać z funkcji AWS Lambda wyzwalanej przez AWS CloudWatch, która obudzi Twój backend na czas przy każdej codziennej aktualizacji.
Proste żądanie AWS Lambda i AWS CloudWatch
AWS Lambda to bezserwerowa platforma obliczeniowa. Do naszych celów potrzebujemy tylko podstaw tej platformy. Będziesz potrzebować konta AWS.
Najpierw zaloguj się do AWS za pomocą swojego konta i znajdź konsolę zarządzania Lambda. Na przykład dla us-east-2
można go znaleźć pod adresem https://us-east-2.console.aws.amazon.com/lambda/home.
Jeśli nie jest jeszcze zaznaczone, przejdź do sekcji „Funkcje”:
Tutaj stworzymy naszą funkcję od podstaw, klikając „Utwórz funkcję”. Nadajmy mu nazwę wyjaśniającą. Będziemy używać Node.js jako języka uruchomieniowego. Następnie kliknij następną „Utwórz funkcję”, aby ją sfinalizować.
Przekieruje nas na stronę nowej funkcji, gdzie możemy napisać nasz kod w index.js
.
Zaimplementujmy naszą pierwszą funkcję lambda. Ponieważ nie mamy żadnych zależności zewnętrznych, musimy użyć podstawowych modułów Node.js. (Jeśli zamiast tego chcesz włączyć zależności innych firm, postępuj zgodnie z tym przewodnikiem z AWS.)
Upewnij się, że nazwa eksportowanej metody (w tym przypadku handler
) odpowiada parametrowi „Handler” na stronie:
Reszta to proste żądanie GET
do twojego zaplecza:
const https = require('https'); exports.handler = async (event) => { return new Promise((resolve, reject) => { https.get(process.env.HEROKU_APP_URL, (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { resolve(JSON.parse(data)); }); }).on("error", (err) => { reject("Error: " + err.message); }); }); };
Upewnij się, że ustawiłeś zmienną środowiskową HEROKU_APP_URL
na stronie i zapisz konfigurację:
Ostatnim krokiem jest dodanie reguły wyzwalacza CloudWatch, aby uruchomić tę funkcję dziesięć minut przed każdą codzienną aktualizacją — w tej serii artykułów działa to do 23:50:
Naszym typem reguły wyzwalacza CloudWatch będzie „Wyrażenie harmonogramu” i, zgodnie z przyjętym formatem, naszym wyrażeniem cron będzie cron(50 23 * * ? *)
.
Skonfigurowaliśmy teraz naszą funkcję AWS Lambda tak, aby była wyzwalana przez naszą regułę CloudWatch.
Teraz zasilamy nasze statyczne strony internetowe: Gatsby/React i Netlify
Dzięki odrobinie AWS Lambda/CloudWatch dodanej do naszego backendu Node.js/MongoDB/Heroku oraz generowaniu i hostowaniu naszego interfejsu Gatsby i Netlify, nasza aplikacja jest gotowa!
Wcześniej udostępniłem link do demonstracji na żywo, ale zachęcam do wypróbowania ulepszonej wersji mojego prototypu — zawiera kilka dodatkowych zmian, które pokochasz.
Możesz użyć tego jako planu dla podobnych projektów — mam nadzieję, że te artykuły pomogą Ci w szybszym i bardziej opłacalnym prototypowaniu aplikacji. Dziękuje za przeczytanie!