Anders ausgedrückt, viel zu lernen! Am Ende werden Sie nicht nur in Jamstack- und Serverless-Konzepte eintauchen, sondern auch praktische Erfahrungen mit einer wirklich coolen Tech-Kombination sammeln, die Ihnen meiner Meinung nach sehr gefallen wird.
Eine Redwood-App erstellen
Redwood ist ein Framework für Serverless-Anwendungen, das React (für Frontend-Komponenten), GraphQL (für Daten) und Prisma (für Datenbankabfragen) zusammenführt.
Es gibt andere Frontend-Frameworks, die wir hier verwenden könnten. Ein Beispiel ist Bison, das von Chris Ball entwickelt wurde. Es nutzt GraphQL auf ähnliche Weise wie Redwood, verwendet jedoch eine etwas andere Zusammenstellung von GraphQL-Bibliotheken, wie Nexus anstelle von Apollo Client und GraphQL Codegen anstelle der Redwood CLI. Es ist jedoch erst seit wenigen Monaten auf dem Markt, sodass das Projekt im Vergleich zu Redwood, das seit Juni 2019 in der Entwicklung ist, noch sehr neu ist.
Es gibt viele großartige Redwood Starter-Vorlagen, mit denen wir unsere Anwendung schnell erstellen könnten. Ich möchte jedoch damit beginnen, ein Redwood-Boilerplate-Projekt zu generieren und die verschiedenen Teile einer Redwood-App zu betrachten. Wir werden das Projekt dann Stück für Stück aufbauen.
Wir müssen Yarn installieren, um die Redwood CLI verwenden zu können. Sobald das erledigt ist, führen Sie Folgendes im Terminal aus:
yarn create redwood-app ./csstricks
Wir wechseln nun mit cd in unser neues Projektverzeichnis und starten unseren Entwicklungsserver.
cd csstricks
yarn rw dev
Das Frontend unseres Projekts läuft nun unter localhost:8910. Unser Backend läuft unter localhost:8911 und ist bereit, GraphQL-Abfragen zu empfangen. Standardmäßig enthält Redwood einen GraphiQL-Spielplatz, den wir gegen Ende des Artikels verwenden werden.
Gehen wir im Browser zu localhost:8910. Wenn alles in Ordnung ist, sollte die Redwood-Landingpage geladen werden.

Redwood ist zum Zeitpunkt der Erstellung dieses Artikels in Version 0.21.0. Die Dokumentation warnt davor, sie in der Produktion zu verwenden, bis sie offiziell 1.0 erreicht. Sie haben auch ein Community-Forum, in dem sie Feedback und Anregungen von Entwicklern wie Ihnen begrüßen.
Verzeichnisstruktur
Redwood bevorzugt Konventionen vor Konfiguration und trifft viele Entscheidungen für uns, einschließlich der Wahl der Technologien, der Organisation von Dateien und sogar der Namenskonventionen. Dies kann zu einer überwältigenden Menge an generiertem Boilerplate-Code führen, der schwer zu verstehen ist, insbesondere wenn Sie sich gerade erst damit befassen.
So ist das Projekt aufgebaut
├── api
│ ├── prisma
│ │ ├── schema.prisma
│ │ └── seeds.js
│ └── src
│ ├── functions
│ │ └── graphql.js
│ ├── graphql
│ ├── lib
│ │ └── db.js
│ └── services
└── web
├── public
│ ├── favicon.png
│ ├── README.md
│ └── robots.txt
└── src
├── components
├── layouts
├── pages
│ ├── FatalErrorPage
│ │ └── FatalErrorPage.js
│ └── NotFoundPage
│ └── NotFoundPage.js
├── index.css
├── index.html
├── index.js
└── Routes.js
Machen Sie sich noch keine zu großen Sorgen darüber, was das alles bedeutet; das erste, was Sie bemerken sollten, ist, dass die Dinge in zwei Hauptverzeichnisse aufgeteilt sind: web und api. Yarn Workspaces ermöglichen es jeder Seite, ihren eigenen Pfad im Codebase zu haben.
web enthält unseren Frontend-Code für
- Seiten
- Layouts
- Komponenten
api enthält unseren Backend-Code für
- Funktionshandler
- Schema-Definitionssprache
- Services für die Backend-Geschäftslogik
- Datenbankclient
Redwood geht von Prisma als Datenspeicher aus, aber wir werden stattdessen Fauna verwenden. Warum Fauna, wenn wir genauso gut Firebase nutzen könnten? Nun, das ist einfach eine persönliche Präferenz. Nachdem Google Firebase übernommen hatte, starteten sie eine Echtzeit-Dokumentendatenbank, Cloud Firestore, als Nachfolger der ursprünglichen Firebase Realtime Database. Durch die Integration in das größere Firebase-Ökosystem hätten wir Zugriff auf eine größere Bandbreite an Funktionen als Fauna bietet. Gleichzeitig gibt es sogar eine Handvoll von Community-Projekten, die mit Firestore und GraphQL experimentiert haben, aber es gibt keine erstklassige GraphQL-Unterstützung von Google.
Da wir Fauna direkt abfragen werden, können wir das Verzeichnis prisma und alles darin löschen. Wir können auch den gesamten Code in db.js löschen. Löschen Sie die Datei nur nicht, da wir sie zum Verbinden mit dem Fauna-Client verwenden werden.
index.html
Wir beginnen mit der Betrachtung der web-Seite, da diese Entwicklern mit Erfahrung in React oder anderen Single-Page-Application-Frameworks vertraut sein sollte.
Aber was passiert eigentlich, wenn wir eine React-App erstellen? Sie nimmt die gesamte Website und verpackt sie in einem großen JavaScript-Ball in index.js, und schiebt diesen JavaScript-Ball dann in den "Root"-DOM-Knoten, der sich in Zeile 11 von index.html befindet.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/png" href="/favicon.png" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="redwood-app"></div> // HIGHLIGHT
</body>
</html>
Während Redwood Jamstack in der Dokumentation und Vermarktung für sich selbst verwendet, betreibt Redwood derzeit noch kein Pre-Rendering (wie es Next oder Gatsby können), ist aber immer noch Jamstack, da es statische Dateien liefert und APIs mit JavaScript für Daten abruft.
index.js
index.js enthält unsere Root-Komponente (diesen großen JavaScript-Ball), die im Root-DOM-Knoten gerendert wird. document.getElementById() wählt ein Element mit einer id aus, die redwood-app enthält, und ReactDOM.render() rendert unsere Anwendung in das Root-DOM-Element.
RedwoodProvider
Die Komponente <Routes /> (und damit alle Seiten der Anwendung) sind innerhalb der <RedwoodProvider>-Tags enthalten. Flash verwendet die Context API, um Nachrichtenobjekte zwischen tief verschachtelten Komponenten zu übergeben. Sie bietet eine typische Nachrichtenanzeigeeinheit für das Rendern der an FlashContext übergebenen Nachrichten.
Der Provider-Komponente von FlashContext ist mit der <RedwoodProvider />-Komponente gebündelt, sodass sie sofort einsatzbereit ist. Komponenten übergeben Nachrichtenobjekte, indem sie sich über den bereitgestellten useFlash-Hook damit verbinden (denken Sie an "Senden und Empfangen").
FatalErrorBoundary
Der Provider selbst ist dann innerhalb der <FatalErrorBoundary>-Komponente enthalten, die <FatalErrorPage> als Prop erhält. Dies setzt Ihre Website standardmäßig auf eine Fehlerseite, wenn alles andere fehlschlägt.
import ReactDOM from 'react-dom'
import { RedwoodProvider, FatalErrorBoundary } from '@redwoodjs/web'
import FatalErrorPage from 'src/pages/FatalErrorPage'
import Routes from 'src/Routes'
import './index.css'
ReactDOM.render(
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodProvider>
<Routes />
</RedwoodProvider>
</FatalErrorBoundary>,
document.getElementById('redwood-app')
)
Routes.js
Router enthält alle unsere Routen und jede Route wird mit einem Route spezifiziert. Der Redwood Router versucht, die aktuelle URL mit jeder Route abzugleichen, stoppt, wenn er eine Übereinstimmung findet, und rendert dann nur diese Route. Die einzige Ausnahme ist die notfound-Route, die eine einzelne Route mit einer notfound-Prop rendert, wenn keine andere Route übereinstimmt.
import { Router, Route } from '@redwoodjs/router'
const Routes = () => {
return (
<Router>
<Route notfound page={NotFoundPage} />
</Router>
)
}
export default Routes
Seiten
Nachdem unsere Anwendung eingerichtet ist, beginnen wir mit der Erstellung von Seiten! Wir verwenden den Redwood CLI generate page-Befehl, um eine benannte Routenfunktion namens home zu erstellen. Diese rendert die HomePage-Komponente, wenn sie dem URL-Pfad / entspricht.
Wir können auch rw anstelle von redwood und g anstelle von generate verwenden, um Tipparbeit zu sparen.
yarn rw g page home /
Dieser Befehl führt vier separate Aktionen aus
- Er erstellt
web/src/pages/HomePage/HomePage.js. Der im ersten Argument angegebene Name wird großgeschrieben und "Page" angehängt. - Er erstellt eine Testdatei unter
web/src/pages/HomePage/HomePage.test.jsmit einem einzelnen, erfolgreichen Test, damit Sie so tun können, als würden Sie Test-Driven Development betreiben. - Er erstellt eine Storybook-Datei unter
web/src/pages/HomePage/HomePage.stories.js. - Er fügt eine neue
<Route>inweb/src/Routes.jshinzu, die den Pfad/derHomePage-Komponente zuordnet.
HomePage
Wenn wir zu web/src/pages gehen, sehen wir ein Verzeichnis HomePage, das eine Datei HomePage.js enthält. Hier ist, was darin ist:
// web/src/pages/HomePage/HomePage.js
import { Link, routes } from '@redwoodjs/router'
const HomePage = () => {
return (
<>
<h1>HomePage</h1>
<p>
Find me in <code>./web/src/pages/HomePage/HomePage.js</code>
</p>
<p>
My default route is named <code>home</code>, link to me with `
<Link to={routes.home()}>Home</Link>`
</p>
</>
)
}
export default HomePage

HomePage.js Datei wurde als Hauptroute, /, festgelegt.Wir werden unsere Seiten-Navigation in eine wiederverwendbare Layout-Komponente verschieben, was bedeutet, dass wir die Importe für Link und routes sowie <Link to={routes.home()}>Home</Link> löschen können. Dies ist, was uns übrig bleibt:
// web/src/pages/HomePage/HomePage.js
const HomePage = () => {
return (
<>
<h1>RedwoodJS+FaunaDB+Vercel 🚀</h1>
<p>Taking Fullstack to the Jamstack</p>
</>
)
}
export default HomePage

AboutPage
Um unsere AboutPage zu erstellen, geben wir fast den gleichen Befehl ein, den wir gerade ausgeführt haben, aber mit about anstelle von home. Wir müssen den Pfad nicht angeben, da er derselbe ist wie der Name unserer Route. In diesem Fall werden sowohl der Name als auch der Pfad auf about gesetzt.
yarn rw g page about

AboutPage.js ist jetzt unter /about verfügbar.// web/src/pages/AboutPage/AboutPage.js
import { Link, routes } from '@redwoodjs/router'
const AboutPage = () => {
return (
<>
<h1>AboutPage</h1>
<p>
Find me in <code>./web/src/pages/AboutPage/AboutPage.js</code>
</p>
<p>
My default route is named <code>about</code>, link to me with `
<Link to={routes.about()}>About</Link>`
</p>
</>
)
}
export default AboutPage
Wir werden ein paar Änderungen an der About-Seite vornehmen, so wie wir es auch bei unserer Home-Seite getan haben. Dazu gehört das Entfernen der Importe für <Link> und routes sowie das Löschen von Link to={routes.about()}>About</Link>. Hier ist das Endergebnis:
Hier ist das Endergebnis
// web/src/pages/AboutPage/AboutPage.js
const AboutPage = () => {
return (
<>
<h1>About 🚀🚀</h1>
<p>For those who want to stack their Jam, fully</p>
</>
)
}

Wenn wir zu Routes.js zurückkehren, sehen wir unsere neuen Routen für home und about. Ziemlich cool, dass Redwood das für uns macht!
const Routes = () => {
return (
<Router>
<Route path="/about" page={AboutPage} name="about" />
<Route path="/" page={HomePage} name="home" />
<Route notfound page={NotFoundPage} />
</Router>
)
}
Layouts
Jetzt wollen wir eine Kopfzeile mit Navigationslinks erstellen, die wir einfach in unsere verschiedenen Seiten importieren können. Wir wollen ein Layout verwenden, damit wir auf so vielen Seiten wie gewünscht Navigation hinzufügen können, indem wir die Komponente importieren, anstatt den Code dafür auf jeder einzelnen Seite schreiben zu müssen.
BlogLayout
Sie fragen sich vielleicht jetzt: "Gibt es einen Generator für Layouts?" Die Antwort lautet... natürlich! Der Befehl ist fast identisch mit dem, was wir bisher getan haben, außer dass wir rw g layout gefolgt vom Namen des Layouts verwenden, anstelle von rw g page gefolgt vom Namen und Pfad der Route.
yarn rw g layout blog
// web/src/layouts/BlogLayout/BlogLayout.js
const BlogLayout = ({ children }) => {
return <>{children}</>
}
export default BlogLayout
Um Links zwischen verschiedenen Seiten zu erstellen, müssen wir
Linkundroutesaus@redwoodjs/routerinBlogLayout.jsimportieren- Eine
<Link to={}></Link>-Komponente für jeden Link erstellen - Eine benannte Routenfunktion, wie z. B.
routes.home(), in dieto={}-Prop für jede Route übergeben
// web/src/layouts/BlogLayout/BlogLayout.js
import { Link, routes } from '@redwoodjs/router'
const BlogLayout = ({ children }) => {
return (
<>
<header>
<h1>RedwoodJS+FaunaDB+Vercel 🚀</h1>
<nav>
<ul>
<li>
<Link to={routes.home()}>Home</Link>
</li>
<li>
<Link to={routes.about()}>About</Link>
</li>
</ul>
</nav>
</header>
<main>
<p>{children}</p>
</main>
</>
)
}
export default BlogLayout
Wir werden im Browser noch nichts anderes sehen. Wir haben das BlogLayout erstellt, es aber noch nicht in Seiten importiert. Lassen Sie uns also BlogLayout in HomePage importieren und die gesamte return-Anweisung mit den BlogLayout-Tags umschließen.
// web/src/pages/HomePage/HomePage.js
import BlogLayout from 'src/layouts/BlogLayout'
const HomePage = () => {
return (
<BlogLayout>
<p>Taking Fullstack to the Jamstack</p>
</BlogLayout>
)
}
export default HomePage

Wenn wir auf den Link zur About-Seite klicken, werden wir dorthin geleitet, können aber nicht zur vorherigen Seite zurückkehren, da wir BlogLayout noch nicht in AboutPage importiert haben. Machen wir das jetzt.
// web/src/pages/AboutPage/AboutPage.js
import BlogLayout from 'src/layouts/BlogLayout'
const AboutPage = () => {
return (
<BlogLayout>
<p>For those who want to stack their Jam, fully</p>
</BlogLayout>
)
}
export default AboutPage

Jetzt können wir durch Klicken auf die Navigationslinks zwischen den Seiten hin und her navigieren! Als nächstes werden wir unser GraphQL-Schema erstellen, damit wir mit Daten arbeiten können.
Fauna Schema Definition Language
Damit dies funktioniert, müssen wir eine neue Datei namens sdl.gql erstellen und das folgende Schema in die Datei eingeben. Fauna wird dieses Schema nehmen und einige Transformationen vornehmen.
// sdl.gql
type Post {
title: String!
body: String!
}
type Query {
posts: [Post]
}
Speichern Sie die Datei und laden Sie sie in den GraphQL Playground von Fauna hoch. Beachten Sie, dass Sie zu diesem Zeitpunkt ein Fauna-Konto benötigen, um fortfahren zu können. Es gibt eine kostenlose Stufe, die für das, was wir tun, gut funktioniert.


Es ist sehr wichtig, dass Redwood und Fauna sich auf die SDL einigen, daher können wir die ursprüngliche SDL, die in Fauna eingegeben wurde, nicht verwenden, da dies keine genaue Darstellung der Typen mehr ist, wie sie in unserer Fauna-Datenbank existieren.

Die Sammlung Post und der Index von Posts werden unverändert angezeigt, wenn wir die Standardabfragen in der Shell ausführen, aber Fauna erstellt einen zwischengeschalteten PostPage-Typ, der ein data-Objekt enthält.
Redwood Schema Definition Language
Dieses data-Objekt enthält ein Array mit allen Post-Objekten in der Datenbank. Wir werden diese Typen verwenden, um eine weitere Schema-Definitionssprache zu erstellen, die sich in unserem graphql-Verzeichnis auf der api-Seite unseres Redwood-Projekts befindet.
// api/src/graphql/posts.sdl.js
import gql from 'graphql-tag'
export const schema = gql`
type Post {
title: String!
body: String!
}
type PostPage {
data: [Post]
}
type Query {
posts: PostPage
}
`
Services
Der posts-Service sendet eine Abfrage an die Fauna GraphQL API. Diese Abfrage fordert ein Array von Posts an, insbesondere den title und body für jeden. Diese sind im data-Objekt von PostPage enthalten.
// api/src/services/posts/posts.js
import { request } from 'src/lib/db'
import { gql } from 'graphql-request'
export const posts = async () => {
const query = gql`
{
posts {
data {
title
body
}
}
}
`
const data = await request(query, 'https://graphql.fauna.com/graphql')
return data['posts']
}
An diesem Punkt können wir graphql-request installieren, einen minimalen Client für GraphQL mit einer Promise-basierten API, mit der GraphQL-Anfragen gesendet werden können.
cd api
yarn add graphql-request graphql
Hängen Sie das Fauna-Autorisierungstoken an den Anforderungsheader an
Bisher haben wir GraphQL für Daten, Fauna für die Modellierung dieser Daten und graphql-request zum Abfragen. Jetzt müssen wir eine Verbindung zwischen graphql-request und Fauna herstellen, was wir tun werden, indem wir graphql-request in db.js importieren und es verwenden, um einen endpoint abzufragen, der auf https://graphql.fauna.com/graphql gesetzt ist.
// api/src/lib/db.js
import { GraphQLClient } from 'graphql-request'
export const request = async (query = {}) => {
const endpoint = 'https://graphql.fauna.com/graphql'
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
authorization: 'Bearer ' + process.env.FAUNADB_SECRET
},
})
try {
return await graphQLClient.request(query)
} catch (error) {
console.log(error)
return error
}
}
Ein GraphQLClient wird instanziiert, um den Header mit einem Autorisierungstoken zu setzen, was den Datenfluss zu unserer App ermöglicht.
Erstellen
Wir werden die Fauna-Shell verwenden und ein paar Befehle der Fauna Query Language (FQL) ausführen, um die Datenbank zu befüllen. Zuerst erstellen wir einen Blogbeitrag mit einem title und body.
Create(
Collection("Post"),
{
data: {
title: "Deno is a secure runtime for JavaScript and TypeScript.",
body: "The original creator of Node, Ryan Dahl, wanted to build a modern, server-side JavaScript framework that incorporates the knowledge he gained building out the initial Node ecosystem."
}
}
)
{
ref: Ref(Collection("Post"), "282083736060690956"),
ts: 1605274864200000,
data: {
title: "Deno is a secure runtime for JavaScript and TypeScript.",
body:
"The original creator of Node, Ryan Dahl, wanted to build a modern, server-side JavaScript framework that incorporates the knowledge he gained building out the initial Node ecosystem."
}
}
Erstellen wir einen weiteren.
Create(
Collection("Post"),
{
data: {
title: "NextJS is a React framework for building production grade applications that scale.",
body: "To build a complete web application with React from scratch, there are many important details you need to consider such as: bundling, compilation, code splitting, static pre-rendering, server-side rendering, and client-side rendering."
}
}
)
{
ref: Ref(Collection("Post"), "282083760102441484"),
ts: 1605274887090000,
data: {
title:
"NextJS is a React framework for building production grade applications that scale.",
body:
"To build a complete web application with React from scratch, there are many important details you need to consider such as: bundling, compilation, code splitting, static pre-rendering, server-side rendering, and client-side rendering."
}
}
Und vielleicht noch einen, um die Dinge zu füllen.
Create(
Collection("Post"),
{
data: {
title: "Vue.js is an open-source front end JavaScript framework for building user interfaces and single-page applications.",
body: "Evan You wanted to build a framework that combined many of the things he loved about Angular and Meteor but in a way that would produce something novel. As React rose to prominence, Vue carefully observed and incorporated many lessons from React without ever losing sight of their own unique value prop."
}
}
)
{
ref: Ref(Collection("Post"), "282083792286384652"),
ts: 1605274917780000,
data: {
title:
"Vue.js is an open-source front end JavaScript framework for building user interfaces and single-page applications.",
body:
"Evan You wanted to build a framework that combined many of the things he loved about Angular and Meteor but in a way that would produce something novel. As React rose to prominence, Vue carefully observed and incorporated many lessons from React without ever losing sight of their own unique value prop."
}
}
Cells
Cells bieten einen einfachen und deklarativen Ansatz für das Abrufen von Daten. Sie enthalten die GraphQL-Abfrage zusammen mit Lade-, Leer-, Fehler- und Erfolgszuständen. Jede Zelle rendert sich automatisch, abhängig von ihrem Zustand.
BlogPostsCell
yarn rw generate cell BlogPosts
export const QUERY = gql`
query BlogPostsQuery {
blogPosts {
id
}
}
`
export const Loading = () => <div>Loading...</div>
export const Empty = () => <div>Empty</div>
export const Failure = ({ error }) => <div>Error: {error.message}</div>
export const Success = ({ blogPosts }) => {
return JSON.stringify(blogPosts)
}
Standardmäßig rendert die Abfrage die Daten mit JSON.stringify auf der Seite, auf der die Zelle importiert wird. Wir werden ein paar Änderungen vornehmen, um die Abfrage zu ändern und die benötigten Daten zu rendern. Also, lassen Sie uns
blogPostsinpostsändern.BlogPostsQueryinPOSTSändern.- Die Abfrage selbst ändern, um den
titleundbodyjedes Posts zurückzugeben. - Das
data-Objekt in der Erfolgs-Komponente zuordnen. - Eine Komponente mit dem
titleundbodyderpostserstellen, die über dasdata-Objekt zurückgegeben werden.
So sieht das aus
// web/src/components/BlogPostsCell/BlogPostsCell.js
export const QUERY = gql`
query POSTS {
posts {
data {
title
body
}
}
}
`
export const Loading = () => <div>Loading...</div>
export const Empty = () => <div>Empty</div>
export const Failure = ({ error }) => <div>Error: {error.message}</div>
export const Success = ({ posts }) => {
const {data} = posts
return data.map(post => (
<>
<header>
<h2>{post.title}</h2>
</header>
<p>{post.body}</p>
</>
))
}
Die POSTS-Abfrage sendet eine Abfrage für posts, und wenn diese abgefragt wird, erhalten wir ein data-Objekt mit einem Array von Posts zurück. Wir müssen das data-Objekt extrahieren, damit wir es durchlaufen und die tatsächlichen Posts erhalten können. Dies tun wir mit Objekt-Destrukturierung, um das data-Objekt zu erhalten, und dann verwenden wir die map()-Funktion, um das data-Objekt zu durchlaufen und jeden Post zu extrahieren. Der title jedes Posts wird mit einem <h2> innerhalb von <header> und der Body mit einem <p>-Tag gerendert.
BlogPostsCell in HomePage importieren
// web/src/pages/HomePage/HomePage.js
import BlogLayout from 'src/layouts/BlogLayout'
import BlogPostsCell from 'src/components/BlogPostsCell/BlogPostsCell.js'
const HomePage = () => {
return (
<BlogLayout>
<p>Taking Fullstack to the Jamstack</p>
<BlogPostsCell />
</BlogLayout>
)
}
export default HomePage

Vercel
Wir erwähnen Vercel im Titel dieses Beitrags, und wir sind endlich an dem Punkt angelangt, an dem wir es brauchen. Insbesondere verwenden wir es, um das Projekt zu erstellen und es auf der gehosteten Plattform von Vercel bereitzustellen, die Build-Vorschauen anbietet, wenn Code in das Projekt-Repository gepusht wird. Wenn Sie also noch keines haben, besorgen Sie sich ein Vercel-Konto. Auch hier funktioniert die kostenlose Preisstufe für diese Arbeit gut.
Warum Vercel statt z.B. Netlify? Das ist eine gute Frage. Redwood begann sogar mit Netlify als seinem ursprünglichen Deploy-Ziel. Redwood hat immer noch viele gut dokumentierte Netlify-Integrationen. Trotz der engen Integration mit Netlify strebt Redwood danach, universell auf so viele Deploy-Ziele wie möglich portierbar zu sein. Dies umfasst nun offizielle Unterstützung für Vercel sowie Community-Integrationen für das Serverless-Framework, AWS Fargate und PM2. Also ja, wir könnten hier Netlify verwenden, aber es ist schön, dass wir eine Auswahl an verfügbaren Diensten haben.
Wir müssen nur eine Änderung an der Projektkonfiguration vornehmen, um sie mit Vercel zu integrieren. Öffnen wir netlify.toml und ändern wir apiProxyPath zu "/api". Dann loggen wir uns bei Vercel ein und klicken auf die Schaltfläche "Projekt importieren", um den Dienst mit dem Projekt-Repository zu verbinden. Hier geben wir die URL des Repos ein, damit Vercel es überwachen kann, und lösen dann einen Build und Deploy aus, wenn es Änderungen bemerkt.

Redwood verfügt über einen voreingestellten Build-Befehl, der unter Vercel sofort einsatzbereit ist.

Wir sind ziemlich weit gekommen, aber obwohl die Website jetzt "live" ist, ist die Datenbank noch nicht verbunden.

Um das zu beheben, fügen wir den FAUNADB_SECRET-Token aus unserem Fauna-Konto zu unseren Umgebungsvariablen in Vercel hinzu.

Jetzt ist unsere Anwendung komplett!

Wir haben es geschafft! Ich hoffe, das begeistert Sie nicht nur für die Arbeit mit Jamstack und Serverless, sondern hat Ihnen auch einige neue Technologien näher gebracht.
Die eigentliche Frage ist "Warum?"
Für neue Entwickler ist es einfacher
Hier ist ein Video von mir, wie ich die Anweisungen befolge. https://www.youtube.com/watch?v=XSutbj2vgZc
Es ist ein dreistündiges Video, was wahrscheinlich länger ist, als es für diese Aufgaben dauern sollte, aber es gibt Gründe dafür...
Ich hoffe, der Autor nimmt sich die Zeit, es anzusehen. Es weist auf Bereiche hin, in denen die Darstellung verbessert werden könnte, identifiziert einige wirklich wichtige Informationen, die einfach fehlen, und korrigiert ein paar offensichtliche Fehler.
Hallo Stephen, danke für das detaillierte Feedback! Als jemand, der lange gebraucht hat, um Webentwicklung zu lernen, habe ich großes Mitgefühl für die Bandbreite der Erfahrungen und Fähigkeiten, die Menschen haben, und ich tue mein Bestes, um meine Artikel für alle so zugänglich wie möglich zu gestalten.
Ich habe nicht die Möglichkeit, einfach in das Backend von CSS-Tricks einzudringen und beliebig Änderungen an Artikeln vorzunehmen. Wenn Sie jedoch spezifische Hinweise auf Dinge haben, die Ihrer Meinung nach geändert oder hinzugefügt werden könnten, bin ich sicher, dass das Team sie gerne berücksichtigen wird!
Ich habe etwa ein Jahr gebraucht, um alles zu lernen, was nur zum Schreiben dieses Artikels benötigt wurde. Wenn Sie also das Projekt in nur drei Stunden zum Laufen bringen konnten, würde ich das als einen riesigen Erfolg betrachten.
Meine Bemühungen waren zu 99 % erfolgreich, aber ich konnte die Authentifizierung nie richtig zum Laufen bringen. Ich konnte die Seite zum Laufen bringen, indem ich die Anmeldeinformationen direkt in den Code in db.js einfügte, aber jede meiner Bemühungen, eine Umgebungsvariable wie im Artikel beschrieben zu verwenden, scheiterte. Der Artikel sagt nicht genau, wie Sie es mit Ihrem Beispiel gemacht haben (woher bekommen Sie den Wert von Fauna (das habe ich selbst herausgefunden), welche Einstellungen verwenden Sie in Vercel (z. B. „Plain Text“ oder „Secret“) und was genau geben Sie als Umgebungsvariable ein (ich gehe davon aus, dass der Name der Variable FAUNADB_SECRET ist und ich habe ein paar verschiedene Dinge im Wert ausprobiert, ohne Erfolg).
Außerdem sagen Sie an einer Stelle: „Lassen Sie uns netlify.toml öffnen“, ohne zu sagen, wo es sich befindet. Ich habe festgestellt, dass Sie „redwood.toml“ meinten und es durch Suchen gefunden.
Es hat auch ziemlich lange gedauert, herauszufinden, was im GraphQL-Playground von Fauna zu tun ist, da Sie zu keinem Zeitpunkt sagen, dass die grünen Schaltflächen (bei Fauna eigentlich nicht grün) angeklickt werden sollten, um das Skript auszuführen, und dass der Text, den Sie im Bild zeigen, tatsächlich die Ausgabe dieses Skripts ist.
Es gab verschiedene andere kleinere Punkte, aber dies sind die wichtigsten, an die ich mich im Moment erinnern kann.
Ich hoffe, ich klinge nicht zu kritisch – ich habe den Artikel geschätzt, mir gefiel die Tatsache, dass Sie Redwood mit verschiedenen Tools ausprobiert haben, und ich hatte mehrere Stunden großartige Unterhaltung damit.
Vielen Dank für diese Hinweise, das ist wirklich hilfreich! Definitiv nicht zu kritisch, ich denke, ich war ursprünglich nur etwas überrumpelt von Ihrem ersten Kritikmedium. Ein dreistündiges Video ist nicht gerade die benutzerfreundlichste Art, Feedback zu geben, haha. Aber Sie haben Recht, dass die Sache mit den Umgebungsvariablen besonders knifflig ist.
Wenn es um die Arbeit mit Umgebungsvariablen geht, ist es schwierig, weil man keine direkten Screenshots oder Codebeispiele zeigen kann, ohne seine Geheimnisse preiszugeben, so dass man immer ein wenig um den heißen Brei herumreden muss. Das war auch das, womit ich am meisten zu kämpfen hatte, als ich diese Technologie zum ersten Mal verwendete, um ein Projekt zu entwickeln. Wir werden das auf jeden Fall berücksichtigen und ich werde sehen, ob wir diese Korrekturen/Klarstellungen in den Artikel aufnehmen können.
„Also ja, wir könnten Netlify hier verwenden, aber es ist schön, dass wir eine Auswahl an verfügbaren Diensten haben.“
Ich freue mich sehr, dass Sie mehr über diese Dienste erfahren haben und es funktioniert auch sehr gut mit Vercel, die kostenlose Preisstufe funktioniert gut für RedwoodJS!