Lass uns ein CMS bauen. Aber anstatt eine Benutzeroberfläche zu erstellen, bekommen wir diese Benutzeroberfläche kostenlos in Form von GitHub selbst! Wir werden GitHub nutzen, um den Inhalt für unseren statischen Website-Generator (es könnte *jeder* statische Website-Generator sein) zu verwalten! Hier ist die Essenz: GitHub wird der Ort sein, an dem wir Dateien verwalten, versionieren und speichern, und auch der Ort, an dem wir Inhalte bearbeiten. Wenn Bearbeitungen stattfinden, werden eine Reihe von Automatisierungen unsere Inhalte testen, verifizieren und schließlich auf Cloudflare bereitstellen.
Den vollständigen Code für das Projekt findest du auf GitHub. Ich betreibe meine eigene Website, jonpauluritis.com, genau auf diese Weise.
Wie sieht der vollständige Stack aus?
Hier ist der Technologie-Stack, mit dem wir in diesem Artikel arbeiten werden
- Jeder Markdown-Editor (Optional. z.B. Typora.io)
- Ein statischer Website-Generator (z.B. Metalsmith)
- Github mit GitHub Actions (CICD und Deployment)
- Cloudflare Workers
Warum sollte dich dieses Setup interessieren? Dieses Setup ist potenziell der schlankste, schnellste, günstigste (~5 $/Monat) und einfachste Weg, eine Website (oder Jamstack-Site) zu verwalten. Es ist sowohl aus technischer als auch aus Benutzeroberflächen-Sicht fantastisch. Dieses Setup ist so fantastisch, dass ich buchstäblich Aktien von Microsoft und Cloudflare gekauft habe.
Aber bevor wir anfangen…
Ich werde dich nicht durch die Einrichtung von Konten bei diesen Diensten führen, das kannst du sicher selbst. Hier sind die Konten, die du einrichten musst:
- GitHub (Melde dich für GitHub Actions an.)
- Cloudflare Workers Sites (Dies ist diejenige, die 5 $/Monat kostet.)
Ich würde auch Typora für ein fantastisches Markdown-Schreiberlebnis empfehlen, aber Markdown-Editoren sind eine sehr persönliche Sache, also verwende den Editor, der sich für dich richtig anfühlt.
Projektstruktur
Um dir eine Vorstellung davon zu geben, wohin wir gehen, hier ist die Struktur des abgeschlossenen Projekts
├── build.js
├── .github/workflows
│ ├── deploy.yml
│ └── nodejs.js
├── layouts
│ ├── about.hbs
│ ├── article.hbs
│ ├── index.hbs
│ └── partials
│ └── navigation.hbs
├── package-lock.json
├── package.json
├── public
├── src
│ ├── about.md
│ ├── articles
│ │ ├── post1.md
│ │ └── post2.md
│ └── index.md
├── workers-site
└── wrangler.toml
Schritt 1: Kommandozeilen-Kram
Wechsle in einem Terminalverzeichnis zu dem Ort, an dem du solche Projekte aufbewahrst, und gib Folgendes ein
$ mkdir cms && cd cms && npm init -y
Das erstellt ein neues Verzeichnis, wechselt dorthin und initialisiert die Verwendung von npm.
Das Nächste, was wir tun wollen, ist, auf den Schultern von Giganten zu stehen. Wir werden eine Reihe von npm-Paketen verwenden, die uns bei Dingen helfen, wobei der Kern die Verwendung des statischen Website-Generators Metalsmith ist.
$ npm install --save-dev metalsmith metalsmith-markdown metalsmith-layouts metalsmith-collections metalsmith-permalinks handlebars jstransformer-handlebars
Neben Metalsmith gibt es noch ein paar andere nützliche Dinge. Warum Metalsmith? Lass uns darüber reden.
Schritt 2: Metalsmith
Ich probiere seit 2-3 Jahren statische Website-Generatoren aus und habe immer noch nicht „den einen“ gefunden. All die großen Namen – wie Eleventy, Gatsby, Hugo, Jekyll, Hexo und Vuepress – sind absolut großartig, aber ich komme über die Einfachheit und Erweiterbarkeit von Metalsmith nicht hinweg.
Als Beispiel wird dieser Code tatsächlich eine Website für dich bauen:
// EXAMPLE... NOT WHAT WE ARE USING FOR THIS TUTORIAL
Metalsmith(__dirname)
.source('src')
.destination('dest')
.use(markdown())
.use(layouts())
.build((err) => if (err) throw err);
Ziemlich cool, oder?
Der Kürze halber gib dies im Terminal ein und wir erstellen eine Struktur und Dateien zum Starten.
Zuerst die Verzeichnisse erstellen
$ mkdir -p src/articles && mkdir -p layouts/partials
Dann die Build-Datei erstellen
$ touch build.js
Als Nächstes erstellen wir einige Layout-Dateien
$ touch layouts/index.hbs && touch layouts/about.hbs && touch layouts/article.hbs && touch layouts/partials/navigation.hbt
Und schließlich richten wir unsere Inhaltsressourcen ein
$ touch src/index.md && touch src/about.md && touch src/articles/post1.md && touch src/articles/post1.md touch src/articles/post2.md
Der Projektordner sollte ungefähr so aussehen
├── build.js
├── layouts
│ ├── about.hbs
│ ├── article.hbs
│ ├── index.hbs
│ └── partials
│ └── navigation.hbs
├── package-lock.json
├── package.json
└── src
├── about.md
├── articles
│ ├── post1.md
│ └── post2.md
└── index.md
Schritt 3: Lass uns etwas Code hinzufügen
Um Platz (und Zeit) zu sparen, kannst du die unten stehenden Befehle verwenden, um die Inhalte für unsere fiktive Website zu erstellen. Fühle dich frei, in „articles“ einzutauchen und deine eigenen Blogbeiträge zu erstellen. Der Schlüssel ist, dass die Beiträge einige Metadaten (auch „Front Matter“ genannt) benötigen, um korrekt generiert werden zu können. Die Dateien, die du bearbeiten möchtest, sind index.md, post1.md und post2.md.
Die Metadaten sollten etwa so aussehen:
---
title: 'Post1'
layout: article.hbs
---
## Post content here....
Oder, wenn du faul bist wie ich, benutze diese Terminalbefehle, um Mock-Inhalte von GitHub Gists zu deiner Seite hinzuzufügen
$ curl https://gist.githubusercontent.com/jppope/35dd682f962e311241d2f502e3d8fa25/raw/ec9991fb2d5d2c2095ea9d9161f33290e7d9bb9e/index.md > src/index.md
$ curl https://gist.githubusercontent.com/jppope/2f6b3a602a3654b334c4d8df047db846/raw/88d90cec62be6ad0b3ee113ad0e1179dfbbb132b/about.md > src/about.md
$ curl https://gist.githubusercontent.com/jppope/98a31761a9e086604897e115548829c4/raw/6fc1a538e62c237f5de01a926865568926f545e1/post1.md > src/articles/post1.md
$ curl https://gist.githubusercontent.com/jppope/b686802621853a94a8a7695eb2bc4c84/raw/9dc07085d56953a718aeca40a3f71319d14410e7/post2.md > src/articles/post2.md
Als Nächstes erstellen wir unsere Layouts und Teil-Layouts („Partials“). Wir werden Handlebars.js für unsere Vorlagensprache in diesem Tutorial verwenden, aber du kannst jede beliebige Vorlagensprache verwenden. Metalsmith kann mit so ziemlich allen umgehen, und ich habe keine starken Meinungen zu Vorlagensprachen.
Erstelle das Index-Layout
<!DOCTYPE html>
<html lang="en">
<head>
<style>
/* Keeping it simple for the tutorial */
body {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.navigation {
display: flex;
justify-content: center;
margin: 2rem 1rem;
}
.button {
margin: 1rem;
border: solid 1px #ccc;
border-radius: 4px;
padding: 0.5rem 1rem;
text-decoration: none;
}
</style>
</head>
<body>
{{>navigation }}
<div>
{{#each articles }}
<a href="{{path}}"><h3>{{ title }}</h3></a>
<p>{{ description }}</p>
{{/each }}
</div>
</body>
</html>
Ein paar Anmerkungen:
- Unsere „Navigation“ wurde noch nicht definiert, wird aber letztendlich den Bereich ersetzen, in dem
{{>navigation }}residiert. {{#each }}iteriert durch die „Sammlung“ von Artikeln, die Metalsmith während seines Build-Prozesses generiert.- Metalsmith hat *viele* Plugins, die du für Dinge wie Stylesheets, Tags usw. verwenden kannst, aber das ist nicht das Thema dieses Tutorials, also überlassen wir das dir zum Erkunden.
Erstelle die Über-uns-Seite
Füge Folgendes zu deiner about.hbs-Seite hinzu
<!DOCTYPE html>
<html lang="en">
<head>
<style>
/* Keeping it simple for the tutorial */
body {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.navigation {
display: flex;
justify-content: center;
margin: 2rem 1rem;
}
.button {
margin: 1rem;
border: solid 1px #ccc;
border-radius: 4px;
padding: 0.5rem 1rem;
text-decoration: none;
}
</style>
</head>
<body>
{{>navigation }}
<div>
{{{contents}}}
</div>
</body>
</html>
Erstelle das Artikel-Layout
<!DOCTYPE html>
<html lang="en">
<head>
<style>
/* Keeping it simple for the tutorial */
body {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.navigation {
display: flex;
justify-content: center;
margin: 2rem 1rem;
}
.button {
margin: 1rem;
border: solid 1px #ccc;
border-radius: 4px;
padding: 0.5rem 1rem;
text-decoration: none;
}
</style>
</head>
<body>
{{>navigation }}
<div>
{{{contents}}}
</div>
</body>
</html>
Du hast vielleicht bemerkt, dass dies das exakt gleiche Layout wie die Über-uns-Seite ist. Das ist es. Ich wollte nur abdecken, wie man zusätzliche Seiten hinzufügt, damit du weißt, wie man das macht. Wenn du möchtest, dass diese anders ist, nur zu.
Navigation hinzufügen
Füge Folgendes zur Datei layouts/partials/navigation.hbs hinzu
<div class="navigation">
<div>
<a class="button" href="/">Home</a>
<a class="button" href="/about">About</a>
</div>
</div>
Sicher, es ist nicht viel... aber das hier soll wirklich kein Metalsmith/SSG-Tutorial sein. ¯\_(ツ)_¯
Schritt 4: Die Build-Datei
Das Herz und die Seele von Metalsmith ist die Build-Datei. Der Vollständigkeit halber gehe ich sie Zeile für Zeile durch.
Wir beginnen mit dem Import der Abhängigkeiten
Schneller Hinweis: Metalsmith wurde 2014 erstellt, und das vorherrschende Modulsystem war damals common.js, daher bleibe ich bei require-Statements im Gegensatz zu ES-Modulen. Es ist auch erwähnenswert, dass die meisten anderen Tutorials ebenfalls require-Statements verwenden, sodass das Überspringen eines Build-Schritts mit Babel das Leben hier nur ein wenig weniger komplex macht.
// What we use to glue everything together
const Metalsmith = require('metalsmith');
// compile from markdown (you can use targets as well)
const markdown = require('metalsmith-markdown');
// compiles layouts
const layouts = require('metalsmith-layouts');
// used to build collections of articles
const collections = require('metalsmith-collections');
// permalinks to clean up routes
const permalinks = require('metalsmith-permalinks');
// templating
const handlebars = require('handlebars');
// register the navigation
const fs = require('fs');
handlebars.registerPartial('navigation', fs.readFileSync(__dirname + '/layouts/partials/navigation.hbt').toString());
// NOTE: Uncomment if you want a server for development
// const serve = require('metalsmith-serve');
// const watch = require('metalsmith-watch');
Als Nächstes werden wir Metalsmith einbeziehen und ihm mitteilen, wo er seine Kompilierungsziele finden soll
// Metalsmith
Metalsmith(__dirname)
// where your markdown files are
.source('src')
// where you want the compliled files to be rendered
.destination('public')
Bisher alles gut. Nachdem wir Quelle und Ziel festgelegt haben, werden wir das Markdown-Rendering, das Layout-Rendering einrichten und Metalsmith mitteilen, „Collections“ zu verwenden. Dies ist eine Möglichkeit, Dateien zusammenzufassen. Ein einfaches Beispiel wäre so etwas wie „Blogbeiträge“, aber es könnte wirklich alles sein, zum Beispiel Rezepte, Whiskey-Bewertungen oder was auch immer. Im obigen Beispiel nennen wir die Sammlung „articles“.
// previous code would go here
// collections create groups of similar content
.use(collections({
articles: {
pattern: 'articles/*.md',
},
}))
// compile from markdown
.use(markdown())
// nicer looking links
.use(permalinks({
pattern: ':collection/:title'
}))
// build layouts using handlebars templates
// also tell metalsmith where to find the raw input
.use(layouts({
engine: 'handlebars',
directory: './layouts',
default: 'article.html',
pattern: ["*/*/*html", "*/*html", "*html"],
partials: {
navigation: 'partials/navigation',
}
}))
// NOTE: Uncomment if you want a server for development
// .use(serve({
// port: 8081,
// verbose: true
// }))
// .use(watch({
// paths: {
// "${source}/**/*": true,
// "layouts/**/*": "**/*",
// }
// }))
Als Nächstes fügen wir das Markdown-Plugin hinzu, damit wir Markdown für Inhalte verwenden können, die zu HTML kompiliert werden.
Von dort aus verwenden wir das Layouts-Plugin, um unseren rohen Inhalt in das Layout zu packen, das wir im Layout-Ordner definieren. Du kannst mehr über die Einzelheiten auf der offiziellen Plugin-Website erfahren, aber das Ergebnis ist, dass wir {{{contents}}} in einer Vorlage verwenden können und es funktioniert einfach.
Die letzte Ergänzung zu unserem kleinen Build-Skript wird die Build-Methode sein
// Everything else would be above this
.build(function(err) {
if (err) {
console.error(err)
}
else {
console.log('build completed!');
}
});
Alles zusammen ergibt ein Build-Skript, das so aussehen sollte
const Metalsmith = require('metalsmith');
const markdown = require('metalsmith-markdown');
const layouts = require('metalsmith-layouts');
const collections = require('metalsmith-collections');
const permalinks = require('metalsmith-permalinks');
const handlebars = require('handlebars');
const fs = require('fs');
// Navigation
handlebars.registerPartial('navigation', fs.readFileSync(__dirname + '/layouts/partials/navigation.hbt').toString());
Metalsmith(__dirname)
.source('src')
.destination('public')
.use(collections({
articles: {
pattern: 'articles/*.md',
},
}))
.use(markdown())
.use(permalinks({
pattern: ':collection/:title'
}))
.use(layouts({
engine: 'handlebars',
directory: './layouts',
default: 'article.html',
pattern: ["*/*/*html", "*/*html", "*html"],
partials: {
navigation: 'partials/navigation',
}
}))
.build(function (err) {
if (err) {
console.error(err)
}
else {
console.log('build completed!');
}
});
Ich bin ein Fan von einfach und sauber und meiner bescheidenen Meinung nach wird es nicht einfacher oder sauberer als ein Metalsmith-Build. Wir müssen nur eine schnelle Aktualisierung der package.json-Datei vornehmen und dann können wir dies ausführen
"name": "buffaloTraceRoute",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "node build.js",
"test": "echo \"No Tests Yet!\" "
},
"keywords": [],
"author": "Your Name",
"license": "ISC",
"devDependencies": {
// these should be the current versions
// also... comments aren't allowed in JSON
}
}
Wenn du deine Arbeit sehen möchtest, kannst du die Teile der Build-Datei auskommentieren, die es dir erlauben, dein Projekt zu servieren und Dinge wie npm run build auszuführen. Stelle nur sicher, dass du diesen Code vor der Bereitstellung entfernst.
Arbeiten mit Cloudflare
Als Nächstes arbeiten wir mit Cloudflare zusammen, um Zugriff auf ihre Cloudflare Workers zu erhalten. Hier kommt die 5 $/Monat Kosten ins Spiel.
Jetzt fragst du dich vielleicht: „OK, aber warum Cloudflare? Was ist mit etwas Kostenlosem wie GitHub Pages oder Netlify?“ Das ist eine gute Frage. Es gibt viele Möglichkeiten, eine statische Website bereitzustellen, warum also eine Methode einer anderen vorziehen?
Nun, Cloudflare hat ein paar Vorteile…
Geschwindigkeit und Leistung
Einer der größten Gründe für den Umstieg auf einen statischen Website-Generator ist die Verbesserung der Website-Leistung. Die Verwendung von Cloudflare Workers Sites kann deine Leistung *noch weiter* verbessern.
Hier ist ein Diagramm, das Cloudflare im Vergleich zu zwei konkurrierenden Alternativen zeigt

Der einfache Grund, warum Cloudflare am schnellsten ist: Eine Website wird in über 190 Datenzentren weltweit bereitgestellt. Dies reduziert die Latenz, da die Benutzer die Assets von einem Standort erhalten, der physisch näher an ihnen liegt.
Einfachheit
Zugegebenermaßen kann die anfängliche Konfiguration von Cloudflare Workers etwas knifflig sein, wenn man nicht weiß, wie man Umgebungsvariablen einrichtet. Aber nachdem du die Grundeinstellungen für deinen Computer eingerichtet hast, ist die Bereitstellung auf Cloudflare so einfach wie `wrangler publish` aus dem Verzeichnis der Website. Dieses Tutorial konzentriert sich auf den CI/CD-Aspekt der Bereitstellung auf Cloudflare, der etwas aufwendiger ist, aber immer noch unglaublich einfach im Vergleich zu den meisten anderen Bereitstellungsprozessen.
(Es lohnt sich, GitHub Pages und Netlify zu erwähnen, die in diesem Bereich ebenfalls hervorragend sind. Die Entwicklererfahrung all dieser drei Unternehmen ist erstaunlich.)
Mehr Leistung für das Geld
Während GitHub Pages und Netlify beide kostenlose Stufen haben, ist deine Nutzung auf 100 GB Bandbreite pro Monat (begrenzt) beschränkt. Versteh mich nicht falsch, das ist ein super großzügiges Limit. Aber danach hast du Pech. GitHub Pages bietet nichts mehr als das und Netlify springt auf 45 $/Monat, was Cloudflare's 5 $/Monat sehr vernünftig macht.
| Dienst | Kostenlose Stufe Bandbreite | Bezahlte Stufe Preis | Bezahlte Stufe Anfragen / Bandbreite |
|---|---|---|---|
| GitHub Pages | 100 GB | N/A | N/A |
| Netlify | 100 GB | $45 | ~150K / 400 GB |
| Cloudflare Workers Sites | none | $5 | 10 Mio. / unbegrenzt |
Sicher, es gibt keine kostenlose Stufe für Cloudflare, aber 5 $ für 10 Millionen Anfragen sind ein Schnäppchen. Ich wäre auch nachlässig, wenn ich nicht erwähnen würde, dass GitHub Pages im letzten Jahr einige Ausfälle hatte. Das ist für eine Demo-Website in Ordnung, aber für ein Unternehmen wären das schlechte Nachrichten.
Cloudflare bietet viele zusätzliche Funktionen, die es wert sind, kurz erwähnt zu werden: kostenlose SSL-Zertifikate, kostenlose (und einfache) DNS-Weiterleitung, ein benutzerdefinierter Workers Sites-Domainname für deine Projekte (was großartig für Staging ist), unbegrenzte Umgebungen (z.B. Staging) und die Registrierung eines Domainnamens zum Selbstkostenpreis (im Gegensatz zu den Aufschlagpreisen anderer Registrar).
Bereitstellung auf Cloudflare
Cloudflare bietet einige großartige Tutorials, wie du ihr Cloudflare Workers Produkt nutzen kannst. Wir werden hier die wichtigsten Punkte behandeln.
Stelle zuerst sicher, dass die Cloudflare CLI, Wrangler, installiert ist
$ npm i @cloudflare/wrangler -g
Als Nächstes fügen wir Cloudflare Sites zum Projekt hinzu, so:
wrangler init --site cms
Wenn ich keinen Fehler gemacht und einen Schritt vergessen habe, sollte hier das im Terminal stehen:
⬇️ Installing cargo-generate...
🔧 Creating project called `workers-site`...
✨ Done! New project created /Users/<User>/Code/cms/workers-site
✨ Succesfully scaffolded workers site
✨ Succesfully created a `wrangler.toml`
Es sollte auch einen generierten Ordner im Projekt-Root namens /workers-site sowie eine Konfigurationsdatei namens wrangler.toml geben – hier liegt die Magie.
name = "cms"
type = "webpack"
account_id = ""
workers_dev = true
route = ""
zone_id = ""
[site]
bucket = ""
entry-point = "workers-site"
Du hast vielleicht schon erraten, was als Nächstes kommt… wir müssen der Konfigurationsdatei einige Informationen hinzufügen! Das erste Schlüssel/Wert-Paar, das wir aktualisieren werden, ist die bucket-Eigenschaft.
bucket = "./public"
Als Nächstes müssen wir die Account ID und Zone ID (d. h. die Route für deinen Domainnamen) abrufen. Du findest sie in deinem Cloudflare-Konto ganz unten im Dashboard für deine Domain

Stopp! Bevor du weitermachst, vergiss nicht, auf die Schaltfläche „Get your API token“ zu klicken, um das letzte Konfigurationsteil zu erhalten, das wir benötigen werden. Speichere es auf einem Notizblock oder irgendwo griffbereit, da wir es für den nächsten Abschnitt benötigen.
Puh! Gut, die nächste Aufgabe ist, die Account ID und Zone ID, die wir gerade abgerufen haben, zur .toml-Datei hinzuzufügen
name = "buffalo-traceroute"
type = "webpack"
account_id = "d7313702f333457f84f3c648e9d652ff" # Fake... use your account_id
workers_dev = true
# route = "example.com/*"
# zone_id = "805b078ca1294617aead2a1d2a1830b9" # Fake... use your zone_id
[site]
bucket = "./public"
entry-point = "workers-site"
(Again, those IDs are fake.)
Auch hier sind die IDs gefälscht. Möglicherweise wirst du aufgefordert, Anmeldeinformationen auf deinem Computer einzurichten. Wenn das der Fall ist, führe wrangler config im Terminal aus.
GitHub Actions
Das letzte Puzzleteil ist die Konfiguration von GitHub, um automatische Deployments für uns durchzuführen. Nachdem ich mich bereits mit CI/CD-Setups beschäftigt hatte, war ich auf das Schlimmste vorbereitet, aber erstaunlicherweise ist GitHub Actions für diese Art von Setup sehr einfach.
Wie funktioniert das also?
Stelle zuerst sicher, dass dein GitHub-Konto GitHub Actions aktiviert hat. Es befindet sich technisch noch in der Beta, aber ich bin bisher auf keine Probleme gestoßen.
Als Nächstes müssen wir ein Repository in GitHub erstellen und unseren Code hochladen. Beginne damit, zu GitHub zu gehen und ein Repository zu erstellen.

Dieses Tutorial soll nicht die Feinheiten von Git und/oder GitHub abdecken, aber es gibt eine großartige Einführung. Oder kopiere und füge die folgenden Befehle im Stammverzeichnis des Projekts ein
# run commands one after the other
$ git init
$ touch .gitignore && echo 'node_modules' > .gitignore
$ git add .
$ git commit -m 'first commit'
$ git remote add origin https://github.com/{username}/{repo name}
$ git push -u origin master
Das *sollte* das Projekt zu GitHub hinzufügen. Ich sage das mit ein wenig Zögern, aber hier gehen normalerweise alle Dinge schief. Wenn du zum Beispiel zu viele Befehle ins Terminal eingibst, hat GitHub plötzlich eine Störung oder das Terminal kann den Pfad zu Python nicht lokalisieren. Sei vorsichtig!
Angenommen, wir sind an diesem Punkt vorbei, ist unsere nächste Aufgabe, GitHub Actions zu aktivieren und ein Verzeichnis namens .github/workflows im Stammverzeichnis des Projektverzeichnisses zu erstellen. (GitHub kann dies auch automatisch tun, indem es den „node“-Workflow beim Aktivieren von Actions hinzufügt. Zum Zeitpunkt des Schreibens ist das Hinzufügen eines GitHub Actions Workflows Teil der Benutzeroberfläche von GitHub.)
Sobald wir das Verzeichnis im Projekt-Root haben, können wir die letzten beiden Dateien hinzufügen. Jede Datei wird einen anderen Workflow behandeln
- Ein Workflow, um zu überprüfen, ob Updates zusammengeführt werden können (d. h. das „CI“ in CI/CD)
- Ein Workflow, um Änderungen bereitzustellen, sobald sie in den Master-Branch zusammengeführt wurden (d. h. das „CD“ in CI/CD)
# integration.yml
name: Integration
on:
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test
env:
CI: true
Dies ist ein geradliniger Workflow. So geradlinig, dass ich ihn direkt aus der offiziellen GitHub Actions Dokumentation kopiert und nur geringfügig geändert habe. Lass uns durchgehen, was dort tatsächlich passiert
on:Führe diesen Workflow nur aus, wenn ein Pull-Request für den Master-Branch erstellt wirdjobs:Führe die folgenden Schritte für zwei Node-Umgebungen aus (z. B. Node 10 und Node 12 – Node 12 ist derzeit die empfohlene Version). Dies wird kompilieren, wenn ein Build-Skript definiert ist. Es werden auch Tests ausgeführt, wenn ein Testskript definiert ist.
Die zweite Datei ist unser Bereitstellungsskript und ist etwas aufwendiger.
# deploy.yml
name: Deploy
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
strategy:
matrix:
node-version: [10.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- uses: actions/checkout@master
- name: Build site
run: "npm run build"
- name: Publish
uses: cloudflare/[email protected]
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
Wichtig! Erinnerst du dich an das Cloudflare API-Token, das ich ganz am Anfang erwähnt habe? Jetzt ist es Zeit, es zu verwenden. Gehe zu den Projekteinstellungen und füge ein Geheimnis hinzu. Nenne das Geheimnis CF_API_TOKEN und füge das API-Token hinzu.
Lass uns durchgehen, was in diesem Skript passiert
on:Führe die Schritte aus, wenn Code in den Master-Branch zusammengeführt wirdsteps:Verwende Node.js, um alle Abhängigkeiten zu installieren, verwende Node.js, um die Website zu bauen, und verwende dann Cloudflare Wrangler, um die Website zu veröffentlichen
Hier ist eine kurze Zusammenfassung, wie das Projekt vor dem Ausführen eines Builds aussehen sollte (ohne node_modules):
├── build.js
├── dist
│ └── worker.js
├── layouts
│ ├── about.hbs
│ ├── article.hbs
│ ├── index.hbs
│ └── partials
│ └── navigation.hbs
├── package-lock.json
├── package.json
├── public
├── src
│ ├── about.md
│ ├── articles
│ │ ├── post1.md
│ │ └── post2.md
│ └── index.md
├── workers-site
│ ├── index.js
│ ├── package-lock.json
│ ├── package.json
│ └── worker
│ └── script.js
└── wrangler.toml
Ein GitHub-basiertes CMS
Okay, ich habe es bis hierher geschafft… Mir wurde ein CMS versprochen? Wo ist die Datenbank und meine GUI, in die ich mich einlogge und so?
Keine Sorge, du bist am Ziel! GitHub *ist jetzt dein CMS* und so funktioniert es
- Schreibe eine Markdown-Datei (mit Front Matter).
- Öffne GitHub und gehe zum Projekt-Repository.
- Klicke in das Verzeichnis „Articles“ und lade den neuen Artikel hoch. GitHub fragt, ob ein neuer Branch zusammen mit einem Pull-Request erstellt werden soll. Die Antwort ist ja.
- Nachdem die Integration verifiziert wurde, kann der Pull-Request zusammengeführt werden, was die Bereitstellung auslöst.
- Lehne dich zurück, entspanne dich und warte 10 Sekunden… der Inhalt wird in 164 Rechenzentren weltweit bereitgestellt.
Glückwunsch! Du hast jetzt ein minimales Git-basiertes CMS, das praktisch jeder nutzen kann.
Fehlerbehebungshinweise
- Metalsmith-Layouts können manchmal etwas knifflig sein. Versuche, diese Debug-Zeile vor dem Build-Schritt hinzuzufügen, um nützliche Ausgaben zu erhalten:
DEBUG=metalsmith-layouts npm run build - Gelegentlich musste ich bei GitHub Actions
node_modulesin den Commit aufnehmen, damit es bereitgestellt werden konnte… das war seltsam für mich (und keine empfohlene Vorgehensweise), behob aber die Bereitstellung. - Wenn du nach einer einfachen Möglichkeit suchst, Assets (Bilder, SVGs usw.) zu verwalten, ist dieses Plugin fantastisch: https://github.com/alexgs/metalsmith-assets-improved (danke an @gofango für den Hinweis auf das Versäumnis!)
- Bitte lass mich wissen, wenn du auf Probleme stößt, und wir können sie dieser Liste hinzufügen!
Schöner Artikel, aber GitHub Pages ermöglicht dir dasselbe kostenlos. Ich habe meine Website darauf aufgebaut und Cloudflare-Caching aktiviert, ebenfalls kostenlos. Fehlt mir etwas? Wie ist dieses Setup besser als das im Artikel beschriebene?
Kann ich bitte einen Link zu diesem Projekt auf GitHub bekommen?
Warum würdest du bezahlen? Ich betreibe mehrere Websites wie zavrel.net, codewithjan.com und smartprofitschool.com, die kostenlos auf Netlify bereitgestellt werden, und die Verwendung von Stackbit ist zum Beispiel kinderleicht. Dieses Setup ist einfach zu viel Aufwand :)
Ich stimme Jan zu. Ich betreibe littleireland.co.uk auf Blogger und es ist die reinste Einfachheit, mit riesiger Kapazität. Ich habe auch kostenloses Cloudflare für zusätzliche Sicherheit und Geschwindigkeit eingebunden. Das kostet mich etwa 8 £ pro Jahr für das Ganze.
oder du kannst Blogger (blogspot) für das kostenlose Google Hosting nutzen. Tonnenweise kostenlose Themes für alle Fälle, meine Website über mobile Spiele-Nachrichten zum Beispiel mmorpg.news
Sogar E-Commerce-Themes integriert mit PayPal.
Nachteile – Blogger ist in China gesperrt.
Vielen Dank, ich habe viel gelernt. Es war in der Tat ein sehr nützlicher Artikel!
Cloudflare Pages ist auch kostenlos.
Danke für die Anleitung!
Für Leute, die mit fehlgeschlagenen GitHub Build Actions kämpfen: Wenn du eine Fehlermeldung wie „module not found“ hast, verschiebe `npm install` kurz vor `npm build` in # deploy.yml.
Du musst möglicherweise auch `master` in `main` ändern, damit es richtig ausgelöst wird, und `env: USER: root` in #deploy hinzufügen, direkt nach dem `wrangler`-Aufruf.