Aufbau einer Full-Stack Serverlose Anwendung mit Cloudflare Arbeitnehmer

0
14

Einer meiner Lieblings-Entwicklungen in der software-Entwicklung wurde die Einführung der serverlose. Als Entwickler hat eine Tendenz, sich zu verzetteln in den details des deployment und DevOps, es ist erfrischend, die gegeben werden, ein Modus, der das erstellen von web-Anwendungen, die einfach abstracts Skalierung und Infrastruktur Weg von mir. Serverlose hat mir besser Versand Projekten!

That being said, wenn Sie das neue serverlose, es kann unklar sein, zu übersetzen, wie die Dinge, die Sie bereits wissen, in ein neues Paradigma. Wenn Sie einen front-end-Entwickler sind, können Sie haben keine Erfahrung mit dem, was serverlose vorgibt zu abstrahieren von Ihnen – so wie Sie selbst begonnen?

Heute, ich werde versuchen zu helfen entmystifizieren der praktische Teil der Arbeit mit serverlose indem Sie ein Projekt von der Idee bis zur Produktion, mit Cloudflare Arbeitnehmer. Unser Projekt wird eine tägliche Rangliste, genannt “Repo-Jagd”, inspiriert von Seiten wie Product Hunt und Reddit, wo Nutzer Einreichen können und upvote Coole open-source-Projekte von GitHub und GitLab. Sie können sehen, die endgültige version der Website, hier veröffentlicht.

Arbeitnehmer ist eine serverlose Anwendung Plattform gebaut, auf der Oberseite des Cloudflare-Netzwerk. Wenn Sie ein Projekt veröffentlichen zu Cloudflare Arbeitnehmer, es ist sofort, verteilt auf 180 (und wachsenden) Städten auf der ganzen Welt, was bedeutet, dass unabhängig davon, wo sich Ihre Benutzer befinden, Ihre Arbeitnehmer Anwendung wird Ihnen von einem nahe gelegenen Cloudflare-server mit extrem niedriger Latenz. Auf top von, dass, die Arbeiter-team hat all-in gegangen auf Entwickler-Erfahrung: unsere neueste Version, die zu Beginn dieses Monats, führte ein voll ausgestattetes command line tool namens Wrangler, das die Verwaltung der Gebäude, hochladen und veröffentlichen Ihre serverlose Anwendungen mit ein paar einfach zu erlernende und mächtige Befehle.

Das Ergebnis ist eine Plattform, die es ermöglicht, einfach JavaScript schreiben und bereitstellen einer URL – keine Gedanken mehr über das, was “Andockfenster” bedeutet, oder wenn Ihre Anwendung wird Umfallen, wenn er es auf die Titelseite von Hacker News!

Wenn Sie der Typ, der sehen will, das Projekt vor der Zeit, bevor hopping in ein langes tutorial, haben Sie Glück! Die Quelle für dieses Projekt finden sich auf GitHub. Mit, dass, lassen Sie uns springen in die Befehlszeile ein, und bauen etwas rad.

Die Installation von Wrangler und der Vorbereitung unserer Arbeitsbereich

Wrangler ist das Kommandozeilen-tool zum generieren, erstellen und veröffentlichen von Cloudflare Arbeitnehmer-Projekte. Wir haben es super einfach zu installieren, vor allem, wenn Sie gearbeitet haben mit npm vor:

npm install-g @cloudflare/wrangler

Sobald Sie installiert haben, Wrangler, können Sie den Befehl erstellen um ein neues Projekt. Wrangler-Projekte verwenden Sie “Vorlagen”, die code-repositories gebaut für die Wiederverwendung durch Entwickler, die mit den Arbeitern. Wir pflegen eine wachsende Liste von Vorlagen, um Ihnen dabei helfen, alle Art von Projekten, in die Arbeitnehmer: schauen Sie sich unsere Vorlagen-Galerie, um loszulegen!

In diesem tutorial verwenden wir den “Router” – Vorlage, die Ihnen erlaubt zu erstellen, URL-basierte Projekte auf der Oberseite der Arbeitnehmer. Der generate-Befehl nimmt zwei Argumente: Erstens, der name des Projekts (ich verwende repo-Jagd), und eine Git-URL. Dies ist mein Lieblings-Teil der Befehl erstellen: Sie können alle Arten von Vorlagen, indem Wrangler auf einen GitHub-URL, also die Freigabe, die Verzweigung, und die Zusammenarbeit an Vorlagen ist super einfach. Wir führen den Befehl erstellen jetzt:

wrangler generieren repo-Jagd https://github.com/cloudflare/worker-template-router
cd-repo-Jagd

Die Router-Vorlage enthält Unterstützung für den Aufbau von Projekten mit webpack, so können Sie npm-Module zu Ihrem Projekt und nutzen Sie die JavaScript-Werkzeuge, die Sie kennen und lieben. Darüber hinaus, wie man erwarten könnte, die Vorlage enthält ein Router-Klasse, die Ihnen erlaubt zu handhaben Routen in Ihr Arbeiter, und binden Sie an eine Funktion. Betrachten wir ein einfaches Beispiel: eine Instanz der Router -, handling -, ein GET-request auf / und der Rückgabe einer Antwort an den client:

// index.js
const Router = require(‘./router’)

addEventListener(‘fetch’, event => {
event.respondWith(handleRequest(event.Anfrage))
})

async-Funktion handleRequest(request) {
try {
const r = new Router()
r.get(‘/’, () => new Response(“Hallo, Welt!”))
const bzw. = r erwarten.route(Anfrage)
Rückgabe bzw
} catch (err) {
return new Response(err)
}
}

Alle Arbeitnehmer-Anwendungen beginnen durch das hören auf das fetch-Ereignis, das eine eingehende Anforderung von einem client aus auf Ihre Bewerbung. Innerhalb der Ereignis-listener, es ist gängige Praxis, rufen Sie eine Funktion handleRequest, ein Blick auf die ankommende Anforderung und bestimmt, wie zu reagieren ist. Bei der Bearbeitung von eingehenden fetch-Ereignis, das angibt, eine eingehende Anfrage, die einen Arbeitnehmer Skript sollte immer wieder eine Antwort zurück an den Benutzer: es ist eine ähnliche Anfrage/Antwort-Muster zu viele web-frameworks, wie Express, so dass, wenn Sie gearbeitet haben, mit web-frameworks vor, es sollte fühlen sich sehr vertraut!

In unserem Beispiel werden wir nutzen, ein paar Routen: ein “root” – route (/), die machen die homepage unserer Website; ein Formular für die Einreichung von neuen repos, at /post, und eine spezielle route für die Annahme von POST-Anfragen, wenn ein Nutzer ein repo von der form an /repo.

Aufbau einer route und Rendern eines templates

Die erste route, die wir einrichten, ist das “root” Weg, über den Pfad /. Dies wird sein, wo repos, vorgelegt von der Gemeinde erbracht werden. Für nun, lassen Sie ‘ s erhalten einige übung definieren Sie eine route und Rückkehr plain HTML. Dieses Muster ist Häufig genug in der Arbeiter-Anwendungen, dass es Sinn macht, es zu verstehen, zuerst, bevor wir weitergehen, um einige weitere interessante Dinge!

Um zu beginnen, wir werden aktualisieren index.js zum einrichten einer Instanz von einem Router, der Griff einer GET-Anfragen an /, und rufen Sie die Funktion index aus handlers/index.js (mehr dazu in Kürze):

// index.js
const Router = require(‘./router’)
const index = require(‘./handlers/index’)

addEventListener(‘fetch’, event => {
event.respondWith(handleRequest(event.Anfrage))
})

Funktion handleRequest(request) {
try {
const r = new Router()
r.get(‘/’, index)
return r.route(Anfrage)
} catch (err) {
return new Response(err)
}
}

Wie mit dem Beispiel index.js im vorherigen Abschnitt, die unseren code wartet auf ein fetch-Ereignis und reagiert durch aufrufen der Funktion handleRequest. Der handleRequest-Funktion wird eine Instanz der Router, die rufen Sie die index-Funktion auf alle GET-Anfragen an /. Mit dem router-setup, leiten wir die eingehenden Anfragen mit r.route und schicken Sie es als die Antwort an den client. Wenn etwas schief geht, wir wickeln einfach den Inhalt der Funktion in einen try/catch-block und zur Rückgabe des err an den client (hier eine Anmerkung: in den Bereichen der Produktion, möchten Sie vielleicht etwas robuster ist hier, wie die Protokollierung, um eine Ausnahme monitoring-tool).

Weiterhin die Einrichtung unserer route-handler erstellen wir eine neue Datei, handlers/index.js, das wird nehmen Sie die eingehende Anfrage und senden Sie eine HTML-Antwort an den client:

// handlers/index.js
const headers = { ‘Content-Type’: ‘text/html’ }
const handler = () => {
return new Response(“Hallo, Welt!”, { Header })
}
– Modul.Exporte = hf

Unsere handler-Funktion ist einfach: es gibt eine neue Instanz der Antwort mit dem text “Hello, world!”, sowie ein Header-Objekt, setzt den Content-Type-header auf text/html – das sagt der browser zum Rendern der eingehenden Antwort als HTML-Dokument. Dies bedeutet, dass, wenn ein client eine GET-Anfrage, um die Strecke / eine neue HTML-Antwort wird konstruiert mit dem text “Hallo, Welt!” und an den Benutzer zurückgegeben.

Wrangler hat eine Vorschau-Funktion, ideal zum testen der HTML-Ausgabe unseres neuen Funktion. Lassen Sie uns diese jetzt ausführen, um sicherzustellen, dass unsere Anwendung funktioniert wie erwartet:

wrangler-Vorschau

Der Vorschau-Befehl sollten Sie eröffnen eine neue Registerkarte in Ihrem browser, nach dem Bau Ihrer Arbeitnehmer Anwendung und dem hochladen auf unsere Tests Spielplatz. In der Registerkarte “Vorschau”, sollten Sie Ihre gerenderten HTML-Antwort:

Mit unserem HTML-Antwort erscheinen im browser, lassen Sie die handler-Funktion ein bisschen spannender, indem du einige gut aussehende HTML. Um dies zu tun, werden wir einen entsprechenden index “template” für unsere route-handler: wenn eine Anfrage kommt in die index-handler, wird er rufen Sie die Vorlage und kehren Sie ein HTML-string, dem AUFTRAGGEBER eine angemessene Benutzer-Schnittstelle als Antwort. Um zu beginnen, machen wir ein update handlers/index.js die Rückgabe einer Antwort verwenden Sie unsere Vorlage (und, darüber hinaus, die Einrichtung eines try/catch-block um Fehler abzufangen, und bringt Sie als Antwort):

// handlers/index.js
const headers = { ‘Content-Type’: ‘text/html’ }
const Vorlage = require(‘../templates/index’)

const handler = async () => {
try {
return new Response(template, (), { Header })
} catch (err) {
return new Response(err)
}
}

– Modul.Exporte = hf

Wie Sie sich vorstellen können, die wir benötigen, um eine entsprechende Vorlage! Wir erstellen eine neue Datei, templates/index.js und zurück eine HTML-Zeichenfolge, mit ES6 template strings:

// templates/index.js
const Vorlage = () => {
return <code><h1>Hallo Welt!</h1>`
}

– Modul.Exporte = Vorlage

Unsere template-Funktion gibt einen einfachen HTML-string, der gesetzt ist, um den Körper von unserer Antwort, in handlers/index.js. Für unsere Letzte snippet-templates für unsere erste route, lasst uns etwas tun, etwas interessanter: erstellen einer templates/layout.js Datei, die die base “layout”, dass alle unsere Vorlagen machen wird in. Dies wird es uns ermöglichen, einige konsistente Gestaltung und Formatierung für alle Vorlagen. In templates/layout.js:

// templates/layout.js
const layout = Körper => `
<!doctype html>
<html>
<head>
<meta charset=”UTF-8″>
<Titel>Repo-Jagd</Titel>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<link rel=”stylesheet” href=”https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css”>
</head>
<body>
<div class=”container”>
<div class=”navbar”>
<div class=”navbar-brand”>
Repo-Jagd
Coole open-source-Projekte täglich
</div>
<div class=”navbar-menu”>
<div class=”navbar-Ende”>
<div class=”navbar-item”>
Post repository
</div>
</div>
</div>
</div>
<div class=”section”>
${body}
</div>
</div>
</body>
</html>
`
– Modul.Exporte = layout

Dies ist ein großes Stück HTML-code, aber es brechen, es gibt nur ein paar wichtige Dinge zu beachten: Erstens, das layout variable ist eine Funktion! Ein Körper-variable übergeben wird, dafür vorgesehen, innerhalb eines div-rechts in der Mitte des HTML-snippet. Darüber hinaus werden wir die Bulmahttps://bulma.io) CSS frameworkhttps://bulma.io), die für ein bisschen easy styling in unserem Projekt, und eine Navigationsleiste, um Benutzer zu sagen, *was* diese Website ist, mit einem link hinterlegen, new repositories.

Nutzen Sie unsere layout-Vorlage, wir werden importieren, die es in templates/index.js und wickeln unseren HTML-string mit:

// templates/index.js
const layout = require(‘./layout’)

const Vorlage = () => {
Rückkehr layout(`<h1>Hallo Welt!</h1>`)
}

– Modul.Exporte = Vorlage

Mit, dass, können wir ausführen wrangler erneute Vorschau, um zu sehen, unsere schön gerenderte HTML-Seite, mit ein wenig styling-Hilfe von Bulma:

Speichern und abrufen von Daten mit Arbeiter-KV

Die meisten web-Anwendungen sind nicht sehr nützlich, ohne irgendeine Art von Daten-Persistenz. Arbeiter-KV ist ein Schlüssel-Wert-Speicher wurde für die Verwendung mit Arbeitnehmer – denken Sie an es als super-schnell und Global verteilte Redis. In unserer Anwendung verwenden wir den KV für die Speicherung aller Daten die für unsere Anwendung: jedes mal, wenn ein Nutzer ein neues repository gespeichert werden, KV, und wir werden auch erzeugt, eine tägliche Reihe von repositories zum Rendern auf der Startseite.

Eine kurze Anmerkung: zum Zeitpunkt des Schreibens, die Nutzung des Arbeiter-KV erfordert eine bezahlte Arbeiter zu planen. Lesen Sie mehr in der “Pricing” – Sektion der Arbeiter docs hier.

Innerhalb der ein Arbeitnehmer Anwendung, können Sie beziehen sich auf eine vordefinierte KV-namespace, die wir erstellen werden, wird innerhalb des Cloudflare UI, und binden Sie zu unserer Anwendung, sobald es eingesetzt wurde, um die Arbeitnehmer Anwendung. In diesem tutorial verwenden wir ein KV-namespace genannt REPO_HUNT, und als Teil des deployment-Prozesses stellen wir sicher, dass es zu befestigen, um unsere Anwendung, so dass alle Verweise im code zu REPO_HUNT richtig aufgelöst werden, um die KV-namespace.

Bevor wir hüpfen in die Erstellung der Daten innerhalb unserer namespace, schauen wir uns die Grundlagen der Arbeit mit KV-innen, die Ihre Mitarbeiter Anwendung. In einem gegebenen Namensraum (z.B. REPO_HUNT), wir können einen Schlüssel mit einem bestimmten Wert setzen:

const string = “Hallo, Welt!”
REPO_HUNT.put(“myString”, string)

Wir können auch um den Wert für diesen Schlüssel besitzt, durch die Verwendung von async/await und wartet auf die Verheißung zu beheben:

const getString = async () => {
const string = erwarten REPO_HUNT.get(“myString”)
console.log(string) // “Hallo, Welt!”
}

Die API ist super einfach, das ist toll, für web-Entwickler, die möchten, starten Sie Anwendungen erstellen, mit den Arbeitern zu Plattform, ohne zu Tauchen Sie ein in relationalen Datenbanken oder jede Art von externen Daten-service. In unserem Fall, wir speichern die Daten unserer Anwendung speichern:

  1. Ein repo – Objekt gespeichert auf der Taste repos ist:$id, wo die $id ist eine generierte UUID für einen neu eingereichten repo.
  2. Ein Tag – array gespeichert, auf das der Schlüssel $Datum (z.B. “6/24/2019”), mit einer Liste von repo-IDs, die auf die eingereichten repos für diesen Tag.

Wir werden beginnen, indem die Implementierung der Unterstützung für die Einreichung von repositories, und machen unsere erste schreibt an unsere KV-namespace durch speichern der repository-Daten in das Objekt, das wir oben angegeben. Auf dem Weg, wir erstellen eine einfache JavaScript-Klasse, die für die Verbindung mit unserem Shop – wir machen Sie Gebrauch von dieser Klasse wieder, wenn wir uns bewegen, auf der Darstellung der homepage, wo wir dann das abrufen des repository-Daten, Aufbau einer UI und beenden unsere Beispiel-Anwendung.

Ermöglicht Nutzer-Daten übermittelt

Egal, was die Anwendung ist, so scheint es, dass web-Entwickler am Ende immer um Formen zu schreiben. In unserem Fall erstellen wir eine einfache form für den Benutzer zu übermitteln repositories.

Am Anfang dieses Tutorials richten wir index.js um eingehende GET-Anfragen an die root-route (`/). Zur Unterstützung der Benutzer das hinzufügen neuer repositories, fügen wir eine neue route, die GET /post, die gerendert wird eine Formular-Vorlage, um Benutzer. In index.js:

// index.js

// …

const post = require(‘./handlers/post’)

// …

Funktion handleRequest(request) {
try {
const r = new Router()
r.get(‘/’, index)
r.get(‘/post, post)
return r.route(Anfrage)
} catch (err) {
return new Response(err)
}
}

Neben einer neuen route-handler in index.js wir werden auch hinzufügen handlers/post.js eine neue Funktion, Prozedur, machen eines zugehörigen template als HTML-Antwort an den Benutzer:

// handlers/post.js
const headers = { ‘Content-Type’: ‘text/html’ }
const Vorlage = require(‘../templates/post -‘)

const handler = Anfrage => {
try {
return new Response(template, (), { Header })
} catch (err) {
return new Response(err)
}
}

– Modul.Exporte = hf

Das Letzte Stück des Puzzles ist die HTML-Vorlage, die sich – wie unsere bisherigen Vorlage, Beispiel, wir werden re-verwenden Sie die layout-Vorlage an, die wir gebaut haben, und wickeln Sie ein einfaches drei-Feld-Formular, das exportieren der HTML-string aus templates/post.js:

// templates/post.js
const layout = require(‘./layout’)

const Vorlage = () =>
layout(`
<div>
<h1>Post ein neues repo</h1>
<form action=”/repo” method=”post”>
<div class=”field”>
<label class=”label” for=”name”>Name</label>
<input class=”input” id=”name” name=”name” type=”text” placeholder=”Name” required></input>
</div>
<div class=”field”>
<label class=”label” for=”Beschreibung”>Beschreibung</label>
<input class=”input” id=”Beschreibung” name=”Beschreibung” type=”text” placeholder=”Beschreibung”></input>
</div>
<div class=”field”>
<label class=”label” for=”url”>URL</label>
<input class=”input” id=”url” name=”url” type=”text” placeholder=”URL” required></input>
</div>
<div class=”field”>
<div class=”control”>
<button class=”button-link” type=”submit”>Submit</button>
</div>
</div>
</form>
</div>
<code>)

– Modul.Exporte = Vorlage

Mit wrangler-Vorschau, navigieren wir zu dem Pfad /post und sehen unsere erbrachte form:

Wenn man sich die definition der eigentlichen “form” – tag in unserer Vorlage, werden Sie feststellen, dass wir eine POST-Anforderung an den Pfad /repo. Empfangen der Daten in das Formular, und speichern Sie es in unserem KV-store, wir gehen durch den Prozess der das hinzufügen eines weiteren handler. In index.js:

// index.js

// …

const erstellen = require(‘./Handler/create’)

// …

Funktion handleRequest(request) {
try {
const r = new Router()
r.get(‘/’, index)
r.get(‘/post, post)
r.post(‘/repo’, create)
return r.route(Anfrage)
} catch (err) {
return new Response(err)
}
}

Wenn ein Formular gesendet wird, um einen Endpunkt, es ist geschickt, wie ein query-string. Um uns das Leben leichter, wir werden einschließen das qs-Bibliothek in unser Projekt, dass wir einfach analysieren, die eingehende Abfrage-string als JS-Objekt. In der Befehlszeile wird die qs einfach mit npm. Während wir hier sind, lasst uns auch die Installation von node-uuid-Paket, welches wir später verwenden werden zum generieren von IDs für die neuen eingehenden Daten. Installieren Sie beide verwenden npm install –save-Befehl:

npm install –save-qs-uuid

Mit, dass, können wir die Umsetzung der entsprechenden handler-Funktion für POST /repo. In handlers/create.js:

// handlers/create.js
const qs = require(‘qs’)

const handler = async-request => {
try {
const body = Anfrage erwarten.text()

if (!Körper) {
throw new Error(‘Falsche Daten’)
}

const data = qs.parse(Körper)

// Todo ‘ s:
// – Repo erstellen
// – Speichern repo
// – Fügen Sie bis heute die repos auf der homepage

return new Response (“ok”, { Header: { Position: ‘/’ }, status: 301 })
} catch (err) {
return new Response(err, { status: 400 })
}
}

– Modul.Exporte = hf

Unsere handler-Funktion ist Recht einfach und es fordert den text auf die Anfrage, wartet auf die Verheißung zu beheben, um wieder unsere query-string-body. Wenn kein body-element ist zur Verfügung gestellt mit der bitte, der hf wirft einen Fehler (wieder mit einem status-code 400, Dank unserer try/catch-block). Bei Angabe einer gültigen Körper, nennen wir analysieren die eingeführte qs-Paket, und erhalten Sie einige Daten zurück. Jetzt haben wir die Stub unsere Absichten für den Rest dieses Codes: zunächst erstellen wir ein repo, basierend auf den Daten. Das sparen wir uns-repo, und dann fügen Sie es auf das array der heutigen repos, für die Darstellung auf der home-Seite.

Schreiben unsere repo-Daten, die in den KV, erstellen wir zwei einfache ES6-Klassen, um ein bisschen Licht Validierung und definieren einige Persistenz-Methoden für unsere Datentypen. Während Sie könnten einfach anrufen REPO_HUNT.direkt, wenn Sie die Arbeit mit großen Mengen von ähnlichen Daten, es kann nett sein, um etwas wie das neue Repo(Daten).save() – in der Tat, wir werden etwas umzusetzen fast genau so aus, so dass die Arbeit mit einem Repo ist unglaublich einfach und konsistent.

Wir definieren store/repo.js mit einem Repo-Klasse. Mit dieser Klasse können wir instanziieren neue Repo-Objekte, und mit der Konstruktor-Methode, die wir übergeben können, Sie Daten und überprüfen Sie es, bevor Sie fortfahren, es zu benutzen in unserem code.

// store/repo.js
const uuid = require(‘uuid/v4’)

Klasse Repo – {
Konstruktor({ id, Beschreibung, name, submitted_at, url }) {
diese.id = id || uuid()
diese.Description = Beschreibung

if (!name) {
throw new Error(`Fehlenden Namen in der Daten -`)
} else {
diese.name = name
}

diese.submitted_at = submitted_at || Number(new Date())

try {
const urlObj = new URL(url)
const whitelist = [‘github.com’, ‘gitlab.com’]

if (!die whitelist.einige(gültig sind => valid === urlObj.host)) {
throw new Error(‘Die URL ist nicht ein repository’)
}
} catch (err) {
throw new Error(‘Die angegebene URL ist nicht gültig’)
}

diese.url = url
}

speichern() {
zurück REPO_HUNT.put(`repos ist:${dies.id}`, JSON.stringify(this))
}
}

– Modul.Exporte = Repo

Auch wenn Sie nicht so super vertraut mit der Konstruktor-Funktion im ES6-Klasse, in diesem Beispiel sollten noch relativ leicht zu verstehen. Wenn wir möchten, erstellen Sie eine neue Instanz des Repo -, leiten wir die relevanten Daten an den Konstruktor als Objekt, mit ES6 ist destructuring assignment zu ziehen, jeder Wert in seiner eigenen Schlüssel. Mit diesen Variablen, wir gehen durch jeden von Ihnen, Sie diese.$Schlüssel (z.B. dieser.name, diesem.Beschreibung, etc) auf den übergebenen Wert.

Viele dieser Werte haben einen “Standard” Wert: zum Beispiel, wenn keine ID übergeben wird, den Konstruktor, wir werden einen neuen zu generieren, unter Verwendung unserer zuvor gespeicherten uuid-Paket s v4-Variante zu generieren, die eine neue UUID mit der uuid(). Für submitted_at, wir erstellen eine neue Instanz von Datum und konvertieren Sie es in einen Unix-timestamp, und für die url, wir werden versichern, dass die URL ist sowohl gültig *und* ist aus github.com oder gitlab.com um sicherzustellen, dass Benutzer die Einreichung echten repos.

Mit der speichern-Funktion, die aufgerufen werden können, die auf eine Instanz von Repo wird ein JSON-stringified version der Repo-Instanz in KV, Einstellung der Schlüssel als repos ist:$id. Zurück in handlers/create.js wir werden importieren Sie die Repo-Klasse und speichern Sie eine neue Repo mit unseren bereits geparste Daten:

// handlers/create.js

// …

const Repo = require(‘../Shop/repo -‘)

const handler = async-request => {
try {
// …

const data = qs.parse(Körper)
const repo = new Repo(Daten)
erwarten repo.save()

// …
} catch (err) {
return new Response(err, { status: 400 })
}
}

// …

Mit, dass, Sie ein neues Repo basiert auf eingehenden Daten in das Formular sollte eigentlich dauerhaft in Arbeiter-KV! Während die repo gespeichert wird, wir wollen auch ein anderes Datenmodell, Tag, enthält eine einfache Liste der Repositorys, die wurden von den Benutzern eingereicht für einen bestimmten Tag. Lassen Sie uns eine neue Datei erstellen, store/day.js und Fleisch es aus:

// store/day.js
const heute = () => new Date().toLocaleDateString()
const todayData = async () => {
const Datum = heute()
const beibehalten = erwarten REPO_HUNT.erhalten(Datum)
Rückkehr beibehalten ? JSON.parse(beibehalten) : []
}

– Modul.Exporte = {
hinzufügen: async-Funktion(id) {
const Datum = heute()
let ids = erwarten todayData()
ids = ids.concat(id)
zurück REPO_HUNT.put(Datum, JSON.stringify(ids))
}
}

Beachten Sie, dass der code für diese noch nicht einmal einer Klasse — es ist ein Objekt mit den Schlüssel-Wert-Paaren, wobei die Werte sind Funktionen! Wir werden hinzufügen, mehr dazu gleich, aber die einzige Funktion, die wir definiert haben, hinzufügen, lädt alle vorhandenen repos aus dem heutigen Datum (mit der Funktion heute zum generieren einer Zeichenkette für das Datum, als der Schlüssel im KV), und fügt eine neue Repo, basierend auf dem id-argument an die Funktion übergeben. Zurück in der handlers/create.js wir werden sicher stellen, dass zu importieren und rufen Sie diese neue Funktion, so dass keine neuen repos Hinzugefügt werden sofort auf der heutigen Liste der repos:

// handlers/create.js

// …

const Tag = require(‘../Shop/Tag’)

// …

const handler = async-request => {
try {

// …

erwarten repo.save()
erwarten Tag.add(repo.id)

return new Response (“ok”, { Header: { Position: ‘/’ }, status: 301 })
} catch (err) {
return new Response(err, { status: 400 })
}
}

// …

Unsere repo-Daten, die nun weiterhin in den KV und es ist Hinzugefügt, um eine Liste der repos die von den Benutzern eingereicht für das heutige Datum. Lassen Sie uns nun auf das Letzte Stück unserer tutorial zu nehmen, dass Daten, und machen es auf der homepage.

Darstellung von Daten

An diesem Punkt haben wir umgesetzt, die Darstellung von HTML Seiten in einer Arbeitnehmer Anwendung, als auch die eingehenden Daten, und anhaltenden es zu Arbeiter-KV. Es sollte Sie nicht überraschen zu erfahren, dass die Einnahme von, dass die Daten vom KV, und das Rendern einer HTML-Seite, unsere homepage ist ganz ähnlich wie alles, was wir gemacht haben bis jetzt. Daran erinnern, dass der Pfad / ist gebunden an unsere index-handler: in dieser Datei werden wir möchten, laden Sie die repos für das heutige Datum, und geben Sie diese in die Vorlage ein, um gerendert zu werden. Es gibt ein paar Stücke, die wir implementieren müssen, um zu bekommen, dass die Arbeit zu beginnen, lassen Sie uns betrachten handlers/index.js:

// handlers/index.js

// …
const Tag = require(‘../Shop/Tag’)

const handler = async () => {
try {
lassen Sie repos = Tag erwarten.getRepos()
return new Response(Vorlage(repos), { Header })
} catch (err) {
return new Response (“Fehler! ${err} für ${JSON.stringify(repos)}`)
}
}

// …

Während der Allgemeine Aufbau der Funktion handler sollte die gleiche bleiben, wir sind nun bereit, einige echte Daten in unserer Anwendung. Sollten wir importieren das Tag-Modul, und innerhalb des handlers, Anruf erwarten Tag.getRepos, um eine Liste der repos zurück (keine Sorge, wir werden implementieren, die die entsprechenden Funktionen in Kürze). Mit diesem Satz von repos, wir Sie weitergeben in unserem template-Funktion, was bedeutet, dass wir in der Lage sein, um tatsächlich machen Sie innerhalb der HTML.

Im inneren des Tages.getRepos, die wir brauchen, um die Liste zu laden repo-IDs aus dem inneren KV, und für jeden von Ihnen, laden Sie die entsprechenden repo-Daten aus der KV. In store/day.js:

// store/day.js

const Repo = require(‘./repo -‘)

// …

– Modul.Exporte = {
getRepos: async function() {
const ids = erwarten todayData()
return ids.Länge ? Repo.findMany(ids) : []
},

// …
}

Die getRepos Funktion wiederverwendet, die zuvor definiert todayData Funktion gibt eine Liste der ids. Wenn diese Liste hat *alle* IDs, wir wollen tatsächlich diesen Repositorys abrufen. Wieder rufen wir eine Funktion, die wir noch nicht ganz definiert, aber, importieren Sie die Repo-Klasse und dem aufrufen Repo.findMany, übergeben Sie in unserer Liste von IDs. Wie Sie sich vorstellen können, sollten wir hüpfen über store/repo.js und implementieren Sie die dazugehörige Funktion:

// store/repo.js

Klasse Repo – {
statische findMany(ids) {
Rendite Versprechen.alle(ids.Karte(Repo.finden))
}

static async find(id) {
const beibehalten = erwarten REPO_HUNT.get(`repos ist:${id}`)
const repo = JSON.parse(persistiert)
Rückkehr beibehalten ? neues Repo({ …repo }) : null
}

// …
}

Zur Unterstützung bei der Suche nach allen repos, die für eine Reihe von IDs, die wir definieren zwei Klassen-Ebene oder statischen Funktionen, finden und findMany, die verwendet Versprechen.alle zu nennen, finden Sie für jede ID in der Liste und wartet, bis diese fertig sind, bevor die Lösung der Versprechen. Der Großteil der Logik, im inneren zu finden, sucht die repo-ID (unter Verwendung der vorher definierten Schlüssel, repos ist:$id), liest die JSON-string und gibt eine neu instanziierte Instanz des Repo.

Nun, wir können look-up-repositories von KV, die wir nehmen sollten, die Daten und Rendern Sie in unserer Vorlage. In handlers/index.js wir kamen in den repos array an die template-Funktion definiert templates/index.js. In dieser Datei sehen wir, dass die repos-array -, und render-Abschnitte von HTML-Code für jedes repo drin:

// templates/index.js

const layout = require(‘./layout’)
const dateFormat = submitted_at =>
new Date(submitted_at).toLocaleDateString(‘en-us’)

const repoTemplate = ({ Beschreibung, name, submitted_at, url }) =>
`<div class=”media”>
<div class=”media-content”>
<p>
${name}
</p>
<p>
${description}
</p>
<p>

Eingereicht ${dateFormat(submitted_at)}
</p>
</div>
</div>
`

const Vorlage = repos => {
const renderedRepos = – repos.Karte(repoTemplate)

Rückkehr layout(`
<div>
${
repos.Länge
? renderedRepos.join(“)
: `<p>Keine repos eingereicht wurden, noch nicht!</p>`
}
</div>
`)
}

– Modul.Exporte = Vorlage

Brechen Sie diese Datei herunter, wir haben zwei primäre Funktionen: – Vorlage (eine aktualisierte version des original exportierte Funktion), die ein array von repos, maps, mit Ihnen, indem er repoTemplate, erzeugen Sie ein array von HTML-strings. Wenn repos ist ein leeres array, gibt die Funktion gibt einfach einen p-tag mit einem leeren Zustand. Die repoTemplate-Funktion verwendet destructuring assignment die Variablen Beschreibung, name, submitted_at, und die url aus dem inneren der repo-Objekt an die Funktion übergeben wird, und macht jeden von Ihnen in ziemlich einfachen HTML -, stützte sich auf Bulmas CSS-Klassen, um zügig ein media-Objekt-layout.

Und mit, dass wir fertig sind das schreiben von code für unser Projekt! Nach erfolgreicher Codierung ist ein ziemlich umfangreiches full-stack-Anwendung, die auf die Arbeiter, wir sind auf den letzten Schritt: bereitstellen der Anwendung auf die Arbeitnehmer-Plattform.

Bereitstellung Ihrer Website für die Arbeitnehmer.dev

Jeder Arbeitnehmer kann der Benutzer Anspruch auf eine Befreiung der Arbeiter.dev subdomain, nach der Anmeldung für ein Konto Cloudflare. In Wrangler, haben wir es super einfach zu behaupten, und konfigurieren Sie Ihre subdomain mit subdomain-subkommando. Jedes Konto erhält einen Arbeiter.dev subdomain, also wählen Sie klug!

wrangler subdomain my-cool-subdomain

Mit einer subdomain konfiguriert haben, können wir stellen nun unseren code! Die name-Eigenschaft im wrangler.toml zeigen, wird die Letzte URL, die in unserer Applikation eingesetzt werden, um: in meinem codebase, der name wird auf repo-Jagd, und meine subdomain ist signalnerve.Arbeiter.dev, also meine endgültige URL für mein Projekt repo-Jagd.signalnerve.Arbeiter.dev. Lassen Sie uns das Projekt bereitstellen, mit dem Befehl “veröffentlichen”:

wrangler veröffentlichen

Bevor wir uns ansehen können, das Projekt im browser haben wir einen weiteren Schritt ausführen: gehen Sie in die Cloudflare-Benutzeroberfläche, erstellen einer KV-namespace, und die Bindung an unser Projekt. Um diesen Prozess zu starten, loggen Sie sich in Ihr Cloudflare dashboard, und wählen Sie die “Arbeiter” – Registerkarte auf der rechten Seite der Seite.

Im inneren der Arbeitnehmer Abschnitt in Ihrem dashboard finden Sie die “KV” Menü, und erstellen Sie einen neuen namespace, passend zu den namespace, den Sie in Ihrer Codebasis (wenn Sie anschließend die code-Beispiele, diese werden REPO_HUNT).

In der Liste der KV-namespaces, kopieren Sie die namespace-ID. Zurück in unserem Projekt werden wir Sie eine ” kv-namespaces` Schlüssel zu unserem `wrangler.toml`, unsere neuen namespace in der codebase:

# wrangler.toml
[[kv-namespaces]]
binding = “REPO_HUNT”
id = “$yourNamespaceId”

Um sicherzustellen, dass Ihr Projekt mit den neuen KV-namespace, veröffentlichen Sie Ihr Projekt ein letztes mal:

wrangler veröffentlichen

Mit, dass, sollte Ihre Anwendung in der Lage, erfolgreich Lesen und schreiben von Ihrem KV-namespace. Öffne mein Projekt-URL zeigen, sollte die endgültige version unserer Projekt — eine vollständige, datengesteuerte Anwendung, ohne zu verwalten-Server, der sich vollständig auf die Arbeiter-Plattform!

Was kommt als Nächstes?

In diesem tutorial bauen wir eine full-stack serverlose Anwendung, die auf die Arbeiter-Plattform, mit Wrangler, Cloudflare ‘ s Kommandozeilen-Werkzeug zum erstellen und bereitstellen von Arbeitnehmer-Anwendungen. Es gibt eine Tonne von Dingen, die Sie tun könnten, um weiterhin das hinzufügen, um diese Anwendung: zum Beispiel die Fähigkeit, upvote Beiträge, oder sogar zu erlauben, Kommentare und andere Arten von Daten. Wenn Sie möchten, um zu sehen das fertige Codebasis für dieses Projekt, schauen Sie auf der GitHub-repo!

Die Arbeiter-team unterhält eine ständig wachsende Liste von neuen Vorlagen zu bauen beginnen Projekte mit – wenn Sie möchten, um zu sehen, was Sie erstellen können, stellen Sie sicher, dass Sie unsere Vorlagen-Galerie. Darüber hinaus stellen Sie sicher, überprüfen Sie heraus einige der tutorials, in den Arbeiter-Dokumentation, wie beispielsweise der Bau einer Lockeren bot, oder ein QR-code-generator.

Wenn Sie ging durch das ganze tutorial (oder wenn Sie Coole Dinge, die Sie teilen möchten), ich würde gerne hören, wie es ging . Wenn Sie interessiert sind, serverlose und halten mit jedem neuen tutorials bin ich veröffentlichen, machen Sie sich ein mein newsletter und abonnieren Sie meinen YouTube-Kanal!