ArticleAufbau eines Blogs mit Nuxt
Es war an der Zeit meine neue Webseite aufzubauen und es sollte unbedingt mit NuxtJS umgesetzt werden. Ich hatte bereits einige positive Tests mit NuxtJS gemacht und festgestellt, dass damit die Vuejs-Entwicklung produktiver geworden ist.
Was wollen wir erreichen
Für unser Blogsystem haben wir die Artikel als Markdowndateien vorliegen. Die Erstellung der Artikelseite und der Übersichtsseite sollen dynamisch erfolgen, d.h. mit einer neuen Markdowndatei soll auch automatisch der neue Artikel erscheinen. Unsere Artikel sollen Metadaten, wie Titel und Beschreibung, enthalten um die Artikelseiten entsprechen für SEO aufzubereiten.
Die Seiten sollen mit Nuxtjs statisch generiert werden. Das Hosting der Seiten vereinfacht sich dadurch extrem und die Search-Engine-Crawler können alle Artikel für ihren Suchindex indizieren.
Auf geht's!
Projekt erstellen und starten
Alle guten Dinge starten im Terminal. Mit folgendem Kommando erstellen wir unsere NuxtJS-Applikation.
npx create-nuxt-app nuxt-blog
Nach dem Aufruf werden einige Eigenschaften zum Projekt abgefragt. Ihr könnt alle Vorgaben übernehmen, achtet aber
darauf, dass als Rendering Mode
unbedingt universal
gewählt wird. Damit ist sichergestellt, dass bei der
Seitengenerierung für jede Seite eine HTML-Datei erzeugt wird.
Die Applikation wurde im neuen Verzeichnis nuxt-blog
erstellt und dort kann die Anwendung mit folgendem Kommando
gestartet werden.
npm run dev
Markdowndateien für Artikel erstellen
Unsere Markdowndateien sollen im neuen Verzeichnis post
hinterlegt werden. Um sie besser zu strukturieren hinterlegen
wir sie in Ordnern mit der entsprechenden Jahreszahl (/post/[year]/[title].md
).
Als Beispiel erstellen wir die Datei /post/2019/nuxtjs-blog.md
---
title: Blogsystem mit Nuxtjs
---
# Blogsystem mit Nuxtjs
Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel
Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel
## Zweite Überschrift
Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel
Dies ist ein Beispiel Dies ist ein Beispiel Dies ist ein Beispiel
``` html
<h1>Beispiel für Quelltext</h1>
<p>Dies ist ein Beispiel Dies ist ein Beispiel</p>
```
Diese Markdowndatei enthält am Anfang einen Metadatenteil (Frontmatter) mit dem Titel des Artikels. Auf diese Daten können wir dann später zugreifen. Und am Ende gibt es ein Quellcodebeispiel, da wir später noch Syntax-Highlighting hinzufügen wollen.
Markdowndatei lesen und darstellen
Wir benötigen noch einen Markdown-Reader. Den installieren wir mit folgendem Kommando:
npm i -D frontmatter-markdown-loader
Und konfigurieren ihn in der nuxt.config.js
.
build: {
/*
** You can extend webpack config here
*/
extend (config, ctx) {
config.module.rules.push({
test: /\.md$/,
loader: 'frontmatter-markdown-loader'
});
}
}
Der Markdown-Reader ist ein Webpack-Loader, d.h. wir können unsere Artikel einfach mit require
oder import
laden.
Und jetzt können wir die Seite erstellen, die uns den Blogartikel darstellt. Der Artikel soll dabei unter dem
URL-Schema /[year]/[title]
erreichbar sein. Also erstellen wir die Seite in /pages/_year/_title.vue
.
<template>
<div>
<nuxt-link to="/">Zurück</nuxt-link>
<p v-html="post.html"/>
</div>
</template>
<script>
export default {
name: "Blogpost",
async asyncData({ params }) {
const post = await import(`../../post/${params.year}/${params.title}.md`);
return { post }
}
}
</script>
Unser Artikel wird in der Methode asyncData
geladen. Durch die Verwendung dieser Methode wird es dann auch später
möglich sein, die Seiten statisch zu generieren.
Über params
können wir auf die Variablen die durch die aufgerufene URL entstehen (dynamisches Routing) zugreifen.
Außerdem benötigen wir eine async/await
-Struktur, um die Promise
von import
aufzulösen.
Das Post
-Objekt enthält nun unseren Artikel im HTML-Format.
Wir können nun unseren Artikel im Browser unter /2019/nuxtjs-blog
aufrufen.
Liste aller Posts für die Startseite generieren
Die Startseite /pages/index.vue
können wir durch folgenden Code ersetzen:
<template>
<div>
<h1>Liste der Blogbeiträge</h1>
<ul>
<li v-for="post in posts">
<nuxt-link :to="post.link">{{ post.attributes.title }}</nuxt-link>
</li>
</ul>
</div>
</template>
<script>
export default {
asyncData() {
const resolve = require.context('~/post', true, /\.md$/);
const posts = resolve.keys().map((key) => {
return {
link: key.slice(0, -3),
attributes: resolve(key).attributes
}
});
return { posts }
}
}
</script>
Um nun eine Liste aller Markdowndateien zu erhalten müssen wir auf require.context
zurückgreifen. Damit kann man sich
alle angeforderten Dateien als Pfad zurückgeben lassen.
Um aus dem Pfad ein Link zu erzeugen müssen wir die Endung .md
mit key.slice(0, -3)
abschneiden.
Durch resolve(key)
erhalten wir das Post
-Objekt und können über attributes
auf die Metadaten zugreifen.
Die Liste der Artikel erscheint nun im Browser auf der Startseite.
Statische Seiten generieren
Um letztendlich die statischen Seiten generieren zu können, benötigt Nuxtjs noch die Information für welche URLs
dies geschehen soll. Das ist notwendig, da wir dynamisches Routing verwenden (zur Erinnerung /_year/_title.vue
).
Dazu erweitern wir die nuxt.config.js
um die Definition der Routen.
import glob from "glob";
...
generate: {
routes: function() {
return glob
.sync('**/*.md', { cwd: 'post' })
.map(filepath => `/${filepath.slice(0, -3)}`)
}
}
}
Der erste Gedanke wäre wieder auf require.context
zurückzugreifen, aber die Webpack-Umgebung steht uns in der
Config-Datei nicht zur Verfügung. Stattdessen können wir direkt über das Dateisystem
(glob
Bibliothek für Wildcard-Suche) unsere Markdowndateien heraussuchen und die Liste der URLs erstellen.
Jetzt können wir die statischen Seiten erzeugen:
npm run generate
Anschließend liegen die erzeugten Dateien im Ordner dist
. Um sich die Seiten anzuschauen empfiehlt es sich einen
simplen HTTP-Server zu verwenden.
npm install -g live-server
Anschließend können Sie die Dateien aus dist
über den HTTP-Server zur Verfügung stellen. Es öffnet sich automatisch
der Browser mit unserer Startseite.
live-server dist
Syntax Highlighting
Zum Abschluss wollen wir unsere Codeblöcke in den Artikeln mit Syntax-Highlighting versehen. Dazu verwenden wir folgendes Paket:
npm install highlight.js --save
HighlightJS ist kein spezielles Vuejs-Paket, deshalb wenden wir es direkt auf den erzeugen HTML-Code in der Methode
mounted
an.
import hljs from 'highlight.js'
import 'highlight.js/styles/darcula.css'
...
export default {
...
mounted () {
document.querySelectorAll('pre code').forEach((block) => {
hljs.highlightBlock(block)
})
}
}
Das verwendete Theme (Farbschema) wurde hier per import
hinzugeladen.
Quellcode
Das ganze Projekt findet ihr auch auf GitHub github.com/urbansky/nuxtjs-blog