Static Site Website Generatoren werden in den letzten 2 Jahren immer beliebter. Es wurde viel darüber geschrieben (wie dies und dies), und es gibt viele großartige Open-Source-Projekte und sogar finanzierte Unternehmen, die Ihnen den Einstieg erleichtern.
Was wäre, wenn ich Ihnen sagen würde, dass Sie einen Static Site Generator mit Ihrem eigenen benutzerdefinierten CMS ohne Datenbank erstellen könnten? Nicht nur das, sondern wir können mit Hello World! in unter 100 Zeilen JavaScript fertig sein.
Artikelserie
- Erstellen Sie ein benutzerdefiniertes CMS für einen serverlosen Static Site Generator (Sie sind hier!) + Repo
- Erstellen Sie ein benutzerdefiniertes serverloses CMS: Teil 2 + Repo
Das historische Problem mit Static Site Generatoren ist, dass sie normalerweise erfordern, dass Inhalte in Markdown verfasst werden. Das funktioniert gut für Entwickler, aber nicht so gut für Kunden, die es gewohnt sind, in einer CMS-Autorenumgebung zu arbeiten. Die Erstellung einer solchen Umgebung bedeutete traditionell die Notwendigkeit, eine Datenbank zur Verwaltung von Authentifizierung, Speicherung von Inhalten und Hochladen von Medien zu erstellen.
Dank des Aufstiegs sogenannter serverloser Architekturen (auch bekannt als Backend as a Service) ist dies nicht mehr der Fall.
In dieser Demo erstellen wir das Grundgerüst eines Static Site Generators mit Inhalten, die von einem Administrator über ein Standard-Webformular erstellt werden (keine Datenbank erforderlich).
Um dies zu erreichen, werden wir verwenden
- Eine serverlose Webanwendungsarchitektur (AWS SDK für JavaScript, Amazon Cognito, IAM und S3)
- Eine Frontend-Template-Engine (JSRender).
Sehen Sie die vollständigen Dateien für dieses Proof-of-Concept- Demo-Projekt auf GitHub.
Richten Sie eine statische Website auf Amazon S3 ein
Melden Sie sich zunächst für ein Konto bei Amazon Web Services (AWS) an, falls Sie dies noch nicht getan haben. Sobald Sie ein AWS-Konto haben, ist es einfach, eine statische Website auf AWS Simple Storage Service (S3) zu hosten.
Erstellen Sie zuerst einen Bucket und wählen Sie dann unter „Static Website Hosting“ in den Eigenschaften „Enable website hosting“ aus und legen Sie das Indexdokument so fest, dass es auf die Homepage der Website (`index.html`) verweist.
Erstellen Sie als Nächstes eine Bucket-Richtlinie, um Ihre Website öffentlich lesbar zu machen. Informationen zur Einrichtung von Bucket-Berechtigungen finden Sie in der AWS S3-Dokumentation. Zusätzlich benötigen wir eine Richtlinie, die es einem Administrator ermöglicht, Inhaltsänderungen zu speichern.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Weitere detaillierte Informationen zum Hosten einer statischen Website auf S3, einschließlich auf einer Ihrer eigenen Domains, finden Sie unter Hosting einer statischen Website auf Amazon Web Services.
Erstellen Sie statische Website-Dateien
Erstellen Sie ein neues Verzeichnis für Ihr Projekt. Erstellen Sie eine einfache Projektseite oder wählen Sie ein einfaches Beispiel aus Ihrem bevorzugten Frontend-Framework. In unserer Demo verwenden wir das Jumbotron-Beispiel von Bootstrap.
Laden Sie die Dateien in den von Ihnen erstellten S3-Bucket hoch. Sobald der Upload abgeschlossen ist, wählen Sie den S3-Bucket aus und sehen Sie sich die Eigenschaften an. Klicken Sie auf den Endpunkt-Link und Sie können Ihre Website anzeigen.
Erstellen Sie Administratoranmeldung
Amazon Cognito bietet eine einfache Möglichkeit, einer Website einen Authentifizierungsfluss hinzuzufügen.
Der erste Schritt in diesem Prozess ist die Erstellung einer UserPool. Navigieren Sie in der AWS-Konsole zu Amazon Cognito und erstellen Sie einen Benutzerpool mit den Standardeinstellungen. Lesen Sie mehr über Benutzerpools in der AWS-Dokumentation.
Nachdem Ihr Benutzerpool erstellt wurde, müssen Sie eine App mit Zugriff auf den Pool hinzufügen. Wählen Sie Ihren Benutzerpool aus, um ihn zu bearbeiten, und wählen Sie dann die Registerkarte „Apps“ aus. Klicken Sie auf die Schaltfläche „Eine App hinzufügen“ und geben Sie Ihrer App einen Namen. Beim Hinzufügen einer App ist es sehr wichtig, das Kontrollkästchen Client-Geheimnis generieren zu deaktivieren, da das JavaScript im Browser-SDK keine Apps mit einem Client-Geheimnis unterstützt.

Wir werden unsere Administratorbenutzer direkt in der AWS-Konsole erstellen und ihnen dann Anmeldeinformationen zur Verfügung stellen, mit denen sie sich anmelden können. Nur diese Benutzer können authentifiziert werden, um auf die Generierung der statischen Inhalte für unsere Website zugreifen zu können.
Gehen Sie in den Benutzerpool und wählen Sie Benutzer und Gruppen. Geben Sie Ihre eigenen Informationen ein, damit Sie der erste Administratorbenutzer sein können. Wählen Sie die Option, dem Benutzer eine Einladung per E-Mail zu senden.

Jetzt müssen wir eine Anmeldeseite für unsere Administratoren erstellen. Erstellen Sie ein neues Admin-Verzeichnis im Projekt mit einer index.html mit einem Anmeldeformular darin. In unserer Demo verwenden wir die Bootstrap-Anmeldeseite.
Um unser Formular mit Cognito zu verbinden, müssen wir das Amazon Cognito Identity SDK für JavaScript verwenden. Befolgen Sie die Installationsanweisungen auf der Projektseite, um die Skripte zu unserer Anmeldeseite hinzuzufügen.
Verwenden Sie als Nächstes den Amazon Cognito Identity Service, um einen Administratorbenutzer zu authentifizieren und eine Sitzung für ihn mit dem temporären Passwort, das er per E-Mail erhalten hat, einzurichten.
Fügen Sie unserem Anmeldeformular einen Submit-Event-Listener hinzu, der eine Login-Funktion aufruft, basierend auf dem Authentifizierungsbeispiel von der Amazon Cognito Identity SDK für JavaScript Projektseite.
$('.form-signin').on('submit', function(e) {
e.preventDefault();
var authenticationData = {
Username : $('#inputUsername').val(),
Password : $('#inputPassword').val()
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var poolData = {
UserPoolId : '...', // your user pool id here
ClientId : '...' // your client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : $('#inputUsername').val(),
Pool : userPool
};
cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
newPasswordRequired: function(userAttributes, requiredAttributes) {
$('#form-password').removeAttr('hidden');
$('#form-login').css('display', 'none');
if ($('#inputNewPassword').val() !== '') {
cognitoUser.completeNewPasswordChallenge($('#inputNewPassword').val(), [], this);
}
},
onSuccess: function (result) {
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId : 'us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
Logins : {
'cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX' : result.getIdToken().getJwtToken()
}
});
$.getJSON('index.json', function(data) {
$('.container').html($('#adminForm').render(data));
}).fail(function() {
$('.container').html($('#adminForm').render({}));
});
AWS.config.update({
region: 'us-east-1',
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
Logins: {
'cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX' : result.getIdToken().getJwtToken()
}
})
});
s3 = new AWS.S3({
apiVersion: '2006-03-01',
params: {
Bucket: YOUR_BUCKET_NAME
}
)};
},
onFailure: function(err) {
alert(err);
}
});
});
Wir müssen ein zusätzliches Formular erstellen, das es dem Administrator ermöglicht, ein Passwort zu erstellen. Der Administrator meldet sich mit seinem temporären Passwort an und legt dann ein neues Passwort fest, um die Authentifizierung abzuschließen.
Weitere Informationen zur Arbeit mit Amazon Cognito und Benutzerpools finden Sie in diesen Artikeln
- Amazon Cognito Entwicklerhandbuch
- Zugriff auf Ihre Benutzerpools mit dem Amazon Cognito Identity SDK für JavaScript
- Anpassen des Authentifizierungsflusses von Amazon Cognito Benutzerpools
Erstellen Sie CMS-Administrator
Nach abgeschlossener Anmeldung möchten wir dem Administrator erlauben, Inhalte auf der Website zu bearbeiten. In dieser Demo bearbeiten wir den oberen Jumbotron-Aufruf. Nachdem der Administrator authentifiziert ist, zeigen wir ein Formular mit Eingabefeldern für Website-Informationen, die Überschrift des Aufrufs und den Text an.

Wenn das Formular abgeschickt wird, kombinieren wir die Daten aus dem Formular mit einer Vorlage, um statisches HTML zu generieren. In dieser Demo verwenden wir JSRender als unsere Templating-Engine.
Erstellen Sie die Vorlage für unsere Jumbotron-Seite, indem Sie das HTML kopieren und es als JSX-Vorlage auf unserer Admin-Seite einbetten. Ersetzen Sie den Inhalt durch Vorlagen-Tags, die den Namen der Admin-Bearbeitungsformularfelder zugeordnet sind.
<script type="text/x-jsrender" id="jumbotronTemplate">
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="{{>siteDescription}}">
<meta name="author" content="">
<title>{{>siteTitle}}</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/jumbotron.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-static-top navbar-dark bg-inverse">
<a class="navbar-brand" href="#">{{>siteTitle}}</a>
<ul class="nav navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</nav>
<div class="jumbotron">
<div class="container">
<h1 class="display-3">{{>calloutHeadline}}</h1>
<p>{{>calloutText}}</p>
<p>
<a class="btn btn-primary btn-lg" href="#" role="button">Learn more »</a>
</p>
</div>
</div>
...
Fügen Sie dem Bearbeitungsformular einen Ereignislistener hinzu, um die eingegebenen Daten als JSON-Objekt zu erfassen, und übergeben Sie sie dann an die JSRender-Vorlage, um HTML für den Upload nach S3 im nächsten Schritt zu generieren.
$('.container')
.on('submit', '#form-admin',function(e) {
e.preventDefault();
var formData = {};
var $formFields = $('#form-admin').find('input, textarea, select').not(':input[type=button],:input[type=submit],:input[type=reset]');
$formFields.each(function() {
formData[$(this).attr('name')] = $(this).val();
});
var jumbotronHTML = '<!DOCTYPE html>' + $('#jumbotronTemplate').render(formData);
var file = new File([jumbotronHTML], 'index.html', {type: "text/html", lastModified: new Date()});
...
Statische Website-Dateien speichern
Als Nächstes gewähren wir dem Administrator die Berechtigung, Bearbeitungen in S3 zu speichern, indem wir eine Identity and Access Management (IAM)-Rolle mit einer Lese-/Schreibrichtlinie für unseren S3-Bucket erstellen.
Navigieren Sie in der AWS-Konsole zu IAM und wählen Sie dann „Policies“ aus. Erstellen Sie eine neue Richtlinie mit dem folgenden Richtliniendokument
{
"Version": "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Action": [ "s3:*" ],
"Resource": [ "arn:aws:s3:::BUCKET_NAME/*" ]
} ]
}
Wählen Sie dann „Roles“ aus, erstellen Sie eine neue Rolle und geben Sie ihr einen Namen. Wählen Sie „Role for Identity Provider access“ und dann Grant access to web identity providers aus. Verwenden Sie das Standard-Richtliniendokument für „Verify Role Trust“.

Befestigen Sie im nächsten Schritt die gerade erstellte Richtlinie für den Zugriff auf den S3-Bucket.
Wählen Sie erneut die Registerkarte „Roles“ im IAM-Abschnitt der AWS-Konsole aus. Wählen Sie die gerade erstellte Rolle aus. Unter „Permissions“ sollten Sie unter „Managed Policies“ Ihre Richtlinie für S3 sehen. Wenn nicht, fügen Sie sie jetzt hinzu.

Aktualisieren Sie die AWS-Konfigurationseinstellungen auf der Admin-Seite, um unseren S3-Dienst einzubeziehen.
// Instantiate AWS SDK service objects now that the credentials have been updated.
AWS.config.update({
region: 'BUCKET_REGION',
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'IDENTITY_POOL_ID'
})
});
s3 = new AWS.S3({
apiVersion: '2006-03-01', params: {Bucket: 'BUCKET_NAME'}
});
Der letzte Schritt zur Verbindung unseres Administratorbenutzers mit S3 ist die Erstellung eines Identitätspools. Kehren Sie zu Amazon Cognito in der AWS-Konsole zurück und klicken Sie auf die Schaltfläche Manage Federated Identities, dann auf die Schaltfläche Create new identity pool.
Geben Sie Ihrem Pool einen Namen und erweitern Sie dann den Abschnitt „Authentication providers“. Wählen Sie die Registerkarte Amazon Cognito aus und geben Sie Ihre User Pool ID und App Client ID ein.

Wie Sie sehen können, können Sie zusätzlich zu Amazon Cognito auch andere Authentifizierungsanbieter wie Facebook und Google verwenden. Weitere Informationen finden Sie unter Integrating User Pools with Amazon Cognito Identity.
Fahren Sie mit den übrigen Schritten fort und notieren Sie sich unter „Sample Code“ die Identity Pool Id. Zurück auf unserer Admin-Seite, wenn unser Formular abgeschickt wird, laden wir unsere HTML-Datei nach S3 hoch.
Darüber hinaus erstellen und laden wir, sobald die HTML-Datei erfolgreich hochgeladen wurde, eine JSON-Datei hoch, um unsere Daten zu speichern, damit die neu aktualisierten Werte beim Zurückkehren zum Formular ausgefüllt sind.
var file = new File([jumbotronHTML], 'index.html', { type: "text/html", lastModified: new Date() });
s3.upload({
Key: 'index.html',
Body: file,
ACL: 'public-read',
ContentDisposition: 'inline',
ContentType: 'text/html'
}, function(err, data) {
if (err) {
return alert('There was an error: ', err.message);
}
file = new File([JSON.stringify(formData)], 'index.json');
s3.upload({
Key: 'admin/index.json',
Body: file,
ACL: 'public-read'
}, function(err, data) {
if (err) {
return alert('There was an error: ', err.message);
}
$('#form-admin')
.remove('#success')
.prepend('<p id="success">Update successful! View Website</p>');
});
});
Aktualisieren Sie den authenticateUser onSuccess-Ereignishandler von Cognito, um das Formular mit Werten aus der JSON-Datei als Vorlage zu rendern, falls diese existiert.
$.getJSON('index.json', function(data) {
$('.container').html($('#adminForm').render(data));
}).fail(function() {
$('.container').html($('#adminForm').render({}));
});
Nächste Schritte
- Angesichts der Möglichkeit, statische Inhalte zu generieren und in S3 zu speichern, gibt es viele spannende Möglichkeiten für Webinhalte und Admin-Oberflächen, die erstellt werden können.
- Fügen Sie Bild- und Dateiupload-Funktionen hinzu
- Fügen Sie einen Rich-Text-Editor hinzu
- Verbessern Sie die Anmeldefunktionalität durch Hinzufügen von Passwort vergessen und MFA.
- Erstellen Sie den Admin zum Bearbeiten von Komponenten und Inhalten auf mehreren Seiten.
- Verwenden Sie
contenteditable, um angemeldeten Administratoren die Bearbeitung direkt auf der Seite zu ermöglichen. - Verwalten Sie unterschiedliche Berechtigungsstufen von Benutzern mit Benutzergruppen.
- Entwickeln Sie einen Workflow für die Erstellung eines benutzerdefinierten CMS für jedes Ihrer Kundenprojekte.
- Erstellen Sie Ihre eigene Content-Management-Plattform.
Das ist wirklich, wirklich cool! Ich hätte nie gedacht, AWS-Authentifizierung zu nutzen, um direkt von einer statisch gehosteten Admin-Oberfläche nach S3 (und andere Dinge wie DynamoDB) zu speichern. Einfach genial. Sie können sogar einen separaten S3-Bucket erstellen, um Ihre HTML-Vorlagen zu speichern, die die statisch gehostete Admin-Oberfläche zum Erstellen der Seiten verwendet.
Wie lange dauert es, bis einige von uns NoServerPress schreiben, eine Content-Plattform, bei der sowohl die Admin-Oberfläche als auch die resultierenden Seiten vollständig statisch gehostet werden und es keine zu verwaltenden Server und keine auszuführenden Kommandozeilentools gibt (*), nur schöne WYSIWYG-Website-Bearbeitung?
(* Kommandozeilentools werden wahrscheinlich immer noch der einfachste Weg sein, die HTML-Vorlagen zu erstellen und bereitzustellen, die die Oberfläche verwendet)
Das ist großartig. John ist in vielerlei Hinsicht ein Genie.
Ich bin definitiv daran interessiert, NoServerPress zu machen. =)
Das sieht wirklich interessant aus. Ich hoffe, Sie haben Zeit, einige der nächsten Schritte durchzuführen und das weiter zu verfolgen.
Danke!
Es gibt jetzt ein offizielles Jekyll-Admin-Panel, das genau das für Jekyll tut…
Es ist ziemlich großartig!
https://github.com/jekyll/jekyll-admin
Wenn Sie es nicht live hosten, bietet es nicht die vollen Fähigkeiten wie der AWS-Service. Mit AWS können Sie dasselbe tun, aber live. Das Gleiche, was Sie lokal schreiben, ist dasselbe, was in der Produktion für Benutzeroberflächen und Authentifizierung ist.