Commit ad20f10d authored by Thomas Citharel's avatar Thomas Citharel 🏃🏻
Browse files

Merge branch 'cms/posts/2020/05/publier-un-blog-statique-avec-gridsome' into 'master'

Create Posts “2020/05/publier-un-blog-statique-avec-gridsome”

See merge request !1
parents e3b13ef4 7cecf0a6
Pipeline #309382 passed with stages
in 1 minute and 16 seconds
---
title: Publier un blog statique avec Gridsome
date: 2020-05-22T20:35:53.881Z
tags:
- Gridsome
- blog
- statique
- JAMStack
thumbnail: logo-normal.png
---
**Gridsome** est un *framework* pour générer des sites statiques à l'aide de VueJS et GraphQL.
<!--more-->
On parle aussi de *framework* [JAMStack](https://jamstatic.fr/2019/02/07/c-est-quoi-la-jamstack/), pour Javascript, APIs et *Markup*. En gros, ce terme décrit simplement d'avoir la possibilité d'ajouter des fonctionnalités dynamiques par dessus votre site statique généré à partir de fichiers sources comme du Markdown, le HTML étant hydraté avec l'application Javascript.
Il n'y a pas de fonctionnalités statiques ici, j'ai juste besoin d'un blog, il n'y aura pas grande différence à l'utilisation si jamais vous avez le Javascript activé ou non dans votre navigateur[^1].
J'ai choisi Gridsome car il utilise le *framework* VueJS avec lequel je suis plus familiarisé, mais c'est quasiment le même fonctionnement que [GatsbyJS](https://www.gatsbyjs.com/) qui utilise ReactJS.
J'avais eu l'occasion d'utiliser Gatsby pour [entraide.chatons.org](https://entraide.chatons.org) et j'avais trouvé le concept intéressant. Aujourd'hui, cet article que vous lisez est justement affiché dans une page d'un site statique généré par Gridsome.
Comme indiqué [sur la page de présentation de Gridsome](https://gridsome.org/) : vous prenez des sources de données en entrée, vous effectuez des traitements sur les données (sélection, transformation, affichage) et vous déployez les fichiers HTML et *assets* produits.
## Créer un projet Gridsome
On commence par installer le module qui fournit la ligne de commande :
```shell
yarn global add @gridsome/cli
```
J'utilise [`yarn`](https://yarnpkg.com/) dans les commandes, mais vous pouvez bien sûr utiliser les équivalents `npm` si c'est ce que vous préférez.
Puis on crée un nouveau projet :
```shell
gridsome create mon-site
```
Cela récupère le modèle du projet, le met à jour avec le nom du projet, et installe les dépendances.
On peut alors se mettre dans le dossier du projet nouvellement créé puis lance le serveur de développement, par défaut sur le port 8080.
```shell
cd mon-site
gridsome develop
```
## Structure du projet
Vous devriez avoir une structure de projet équivalente voire égale à celle ci-dessous :
```
├── gridsome.config.js
├── gridsome.server.js
├── package.json
├── README.md
├── src
│   ├── components
│   │   └── README.md
│   ├── favicon.png
│   ├── layouts
│   │   ├── Default.vue
│   │   └── README.md
│   ├── main.js
│   ├── pages
│   │   ├── About.vue
│   │   ├── Index.vue
│   │   └── README.md
│   └── templates
│   └── README.md
├── static
│   └── README.md
└── yarn.lock
```
On voit dans `src/pages/` les fichiers `About.vue` et `Index.vue`, qui correspondent aux deux routes accessibles via la barre de navigation. Notez donc que le routage de base se fait via les fichiers disponibles dans `/pages/`. `Index.vue` correspond à la page d'accueil `/`, et un fichier `MonProjet.vue` donnerait une route `/mon-projet`.
On a également le fichier `Default.vue` dans `/src/layouts/`. Les *layouts* sont utilisés pour envelopper vos pages avec des éléments communs aux pages, typiquement l'en-tête de la page, la barre de navigation, le pied-de-page… Dans nos pages, par exemple `About.vue`, le contenu est enveloppé par l'élément `<Layout>` :
```html
<template>
<Layout>
<h1>About us</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error doloremque omnis animi, eligendi magni a voluptatum, vitae, consequuntur rerum illum odit fugit assumenda rem dolores inventore iste reprehenderit maxime! Iusto.</p>
</Layout>
</template>
```
## Ajout et représentation des données
Le squelette de notre site étant exploré, voyons comment y insérer nos données. Gridsome utilise [GraphQL](https://graphql.org/), un langage de requêtes. Nous avons par exemple un premier exemple de requête GraphQL dans le fichier `layouts/Default.vue`, où le nom du site (défini dans le fichier de configuration `gridsome.config.js`) est récupéré avec la requête suivante :
```graphql
query {
metadata {
siteName
}
}
```
La variable `siteName` est alors disponible via l'expression `$static.metadata.siteName` dans notre template VueJS.
Pour importer nos propres données, prenons l'exemple basique de billets de blog sous forme de fichiers locaux au format Markdown.
Installons les modules [`@gridsome/source-filesystem`](https://gridsome.org/plugins/@gridsome/source-filesystem) afin de récupérer le contenu des fichiers et [`@gridsome/transformer-remark`](https://gridsome.org/plugins/@gridsome/transformer-remark) afin de transformer notre contenu markdown en HTML et surtout convertir l'éventuel *front matter* YAML en métadonnées utilisables.
Nous allons ajouter la configuration donnée en exemple dans `gridsome.config.js` :
```js
module.exports = {
plugins: [
{
use: '@gridsome/source-filesystem',
options: {
typeName: 'BlogPost',
path: './content/blog/**/*.md',
}
}
],
templates: {
BlogPost: '/blog/:year/:month/:day/:title'
}
}
```
Puis créons l'arborescence `content/blog/2020` et un fichier `hello world.md` au bout avec le contenu de base suivant :
```markdown
---
date: 2020-01-05
title: "Hello World"
---
Il s'agit de mon **premier** contenu !
```
On redémarre le serveur de développement Gridsome car on a changé la configuration puis on ouvre [le bac à sable](http://localhost:8080/___explore) GraphQL pour effectuer nos premières requêtes et voir le résultat facilement.
Par exemple, pour récupérer la liste de tous nos posts, on écrira :
```graphql
query {
allBlogPost {
edges {
node {
title,
date(format: "DD/MM/YYYY"),
path
}
}
}
}
```
Si on édite notre page `Index.vue`, on peut rajouter cette requête dans un bloc `<page-query>` et ensuite accéder aux données via `$page.allBlogPost`, comme par comme dans l'exemple suivant où nous rajoutons une liste des billets au template :
```html
<ul v-for="edge in $page.allBlogPost.edges" :key="edge.node.id">
<li>{{ edge.node.title }}</li>
</ul>
```
Ajoutons ensuite un fichier `BlogPost.vue` dans nos `templates/` pour représenter ces entités:
```html
<template>
<Layout>
<article>
<h1>{{ $page.blogPost.title }}</h1>
<span>{{ $page.blogPost.date }}</span>
<div v-html="$page.blogPost.content"></div>
</article>
</Layout>
</template>
<page-query>
query BlogPost($path: String!) {
blogPost(path: $path) {
title,
date(format: "DD/MM/YYYY"),
content
path
}
}
</page-query>
```
Comme on l'a vu, les données de la requête GraphQL `blogPost` sont injectées dans la variable `$page` accessible dans mon template. Maintenant que l'on a une page dédiée pour afficher chaque billet, ajoutons un lien depuis notre liste sur la page `Index.vue`, en changeant notre `<li>` en :
```html
<li>
<g-link :to="edge.node.path">{{ edge.node.title }}</g-link>
</li>
```
La balise `<g-link>` crée lors du rendu des balises `<a>` tout ce qu'il y a de plus basique, mais permet aussi le préchargement des liens (voir les notes de bas de page). En cliquant dessus, on arrive finalement sur notre page montrant un article en particulier.
## Génération et publication
Générons maintenant notre site avec `gridsome build`, puis servons le contenu du dossier `dist`, par exemple avec [serve](https://github.com/vercel/serve) : `serve dist`.
Je vous laisse vérifier que la navigation fonctionne bien et que le HTML produit contient bien notre contenu.
On peut publier le contenu de `dist` là où on le souhaite, voici un exemple de fichier de configuration pour le publier sur Gitlab Pages :
```yaml
image: node:14
deploy:
stage: deploy
script:
- yarn install
- yarn build
- gzip -kv -6 -r public
artifacts:
paths:
- public
```
Je m'arrête là pour parler de Gridsome, mais j'ai quand même prévu de parler de comment gérer mes contenus sur ce site avec [NetlifyCMS](https://www.netlifycms.org/), et comment mettre en place un `chroot` sur un serveur pour y faire un rsync depuis notre CI afin de déployer notre site.
[^1]: Une différence est que si le Javascript est activé, Gridsome est censé observer les liens internes actuellement affichés à l'écran (avec [`IntersectionObserver`](https://developer.mozilla.org/fr/docs/Web/API/Intersection_Observer_API)) pour les précharger afin que les chargements de page soient effectués avant même le clic éventuel sur le lien. Les gains devraient rester minimaux étant donné qu'il n'y a qu'un contenu HTML à récupérer depuis le serveur.
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment