Fermer

février 4, 2020

Comment créer un site WordPress sans tête sur JAMstack


À propos des auteurs

Sarah Drasner est une conférencière primée, chef de l'expérience développeur chez Netlify, membre de l'équipe principale Vue et rédactrice en chef chez CSS-Tricks. Sarah est autrefois…
En savoir plus
Sarah et Geoff

Dans cet article, nous allons créer un site de démonstration et un didacticiel pour WordPress sans tête, y compris un modèle de démarrage! Nous utiliserons le tableau de bord WordPress pour la modification de contenu riche, tout en migrant l'architecture frontale vers JAMstack pour bénéficier d'une sécurité, de performances et d'une fiabilité améliorées. Nous le ferons en configurant une application Vue avec Nuxt, en récupérant les messages de notre application via l'API WordPress.

Dans le premier article de cette série, nous avons parcouru le parcours de Smashing Magazine depuis WordPress à JAMstack. Nous avons couvert les raisons du changement, les avantages qui en découlaient et les obstacles rencontrés en cours de route.

Comme tout grand projet d'ingénierie, l'équipe est sortie de l'autre côté en sachant plus sur le spectre des succès et des échecs au sein de le projet. Dans cet article, nous allons mettre en place un site de démonstration et un didacticiel sur ce que nos recommandations actuelles seraient pour un projet WordPress à grande échelle: conserver un tableau de bord WordPress pour l'édition de contenu riche, tout en migrant l'architecture frontale vers JAMstack pour bénéficier d'une meilleure sécurité, performances et fiabilité.

Nous le ferons en configurant une application Vue avec Nuxt et en utilisant WordPress sans tête – en récupérant les publications de notre application via l'API WordPress. La démo est ici et le dépôt open source est ici .

( Grand aperçu )

 Déployer sur le bouton Netlify Si vous souhaitez ignorer toutes les étapes ci-dessous, nous avons préparé un modèle pour vous. Vous pouvez appuyer sur le bouton de déploiement ci-dessous et le modifier selon vos besoins.

Ce qui suit est un didacticiel complet sur la façon dont nous configurons tout cela. Allons-y!

Entrez dans l'API REST WordPress

L'une des fonctionnalités les plus intéressantes de WordPress est qu'il inclut une API dès la sortie de la boîte. Il existe depuis la fin de 2016 lorsqu'il a été expédié dans WordPress 4.7 et avec lui, des opportunités ont été utilisées pour utiliser WordPress de nouvelles façons. De quelle manière? Eh bien, celui qui nous intéresse le plus aujourd'hui est de savoir comment il permet la séparation du contenu WordPress et du Front End. Alors que la création d'un thème WordPress en PHP était autrefois le seul moyen de développer une interface pour un site WordPress, l'API REST a inauguré une nouvelle ère où les pouvoirs de gestion de contenu de WordPress pouvaient être étendus pour une utilisation en dehors du répertoire WordPress racine sur un serveur – que ce soit une application, un site codé à la main ou même des plateformes différentes. Nous ne sommes plus liés à PHP.

Ce modèle de développement est appelé CMS sans tête . Il convient de mentionner que Drupal et la plupart des autres systèmes de gestion de contenu populaires proposent également un modèle sans tête, donc une grande partie de ce que nous montrons dans cet article n'est pas uniquement spécifique à WordPress.

En d'autres termes, WordPress est utilisé uniquement pour son interface de gestion de contenu (l'administrateur WordPress) et les données qui y sont entrées sont syndiquées n'importe où qui demande les données via l'API. Cela signifie que le même contenu de votre ancien site peut désormais être développé en tant que site statique, application Web progressive ou de toute autre manière tout en continuant d'utiliser WordPress comme moteur de création de contenu.

Mise en route

Faisons quelques hypothèses avant de plonger:

  • WordPress est déjà opérationnel .
    Passer en revue une installation WordPress est en dehors de ce que nous voulons examiner dans cet article et c'est déjà bien documenté .
  • Nous avons du contenu avec lequel travailler .
    Le site ne serait rien sans lui fournir quelques données de l'API REST WordPress.
  • Le front-end est développé dans Vue.
    Nous pourrions utiliser un certain nombre d'autres choses, comme React, Jekyll, Hugo, ou autre . Il se trouve que nous aimons vraiment Vue et, à vrai dire, c'est probablement la direction que le projet Smashing Magazine aurait prise s'ils avaient pu recommencer le processus.
  • Nous utilisons Netlify .
    C'était la plate-forme vers laquelle Smashing a migré, et il est simple de travailler avec. Divulgation complète, Sarah y travaille. Elle y travaille également parce qu'elle aime leur service. 🙂

Configurer Vue avec Nuxt

Comme WordPress, il y a déjà une documentation stellaire pour configurer un projet Vue, et Sarah a un Cours de Master Frontend (tous les matériaux) sont libres et open source sur son GitHub ). Pas besoin de ressasser cela ici.

Mais ce que nous allons réellement faire, c'est créer notre application en utilisant NuxtJS . Il ajoute un tas de fonctionnalités à un projet Vue typique (par exemple, regroupement, rechargement à chaud, rendu côté serveur et routage pour n'en nommer que quelques-unes) que nous aurions autrement à assembler. En d'autres termes, cela nous donne une belle longueur d'avance.

Encore une fois, la mise en place d'un projet NuxtJS est super bien documentée, il n'est donc pas nécessaire d'entrer dans le détail dans ce billet. Ce qui vaut la peine d'entrer, c'est le répertoire du projet lui-même. Ce serait bien de savoir dans quoi nous nous embarquons et où l'API doit aller.

Apprenez à configurer une application Nuxt à partir de zéro – il pourrait être utile de regarder si vous êtes complètement nouveau. ( Regarder sur Vimeo )

Nous allons créer le projet avec cette commande:

 npx create-nuxt-app 

Voici la structure générale d'un projet Nuxt standard, en laissant de côté certains fichiers pour plus de brièveté:

[root-directory]
 ├── .nuxt
├── actifs
├── composants
        ├── AppNavigation.vue // tous les composants que vous réutiliserez
        └── AppFooter.vue
├── dist
├── dispositions
        └── default.vue // cela vous donne une mise en page standard, vous pouvez en faire plusieurs si vous le souhaitez, comme blog.vue, etc. Nous mettons généralement nos navs et pieds de page ici
├── middleware
├── node_modules
├── pages
├── index.vue // tous les composants .vue que nous mettons ici deviendront automatiquement des pages routées!
    └── about.vue
├── plugins
├── statique
| └── index.html
├── magasin
    └── index.js // nous mettrons ici tout état que nous devons partager autour de l'application, y compris les appels à l'API REST pour mettre à jour les données. C'est ce qu'on appelle un magasin Vuex. En créant la page d'index, Nuxt l'enregistre.
└── nuxt.config.js

C'est tout pour notre installation Vue / Nuxt! Nous allons créer un composant qui récupère les données d'un site WordPress en un instant, mais c'est essentiellement ce avec quoi nous travaillons.

Hébergement statique

Avant de connecter l'application Vue avec Netlify, créons un référentiel du projet. Un des avantages d'un service comme Netlify est qu'il peut déclencher un déploiement lorsque des modifications sont transmises à la branche principale (ou à une autre) d'un référentiel. Nous le voudrons certainement. Git est automatiquement initialisé dans une nouvelle installation de Vue, nous pouvons donc ignorer cette étape. Tout ce que nous devons faire est de créer un nouveau référentiel sur GitHub et de pousser le projet local à maîtriser. Tout ce qui est en majuscules est quelque chose que vous allez remplacer par vos propres informations.

 ### Ajouter des fichiers
git add.

### Ajouter une origine distante
git remote add origin git@github.com: USERNAME / REPONAME.git

### Poussez tout vers le référentiel distant
git push -u origin master

Maintenant, nous allons nous diriger vers notre compte Netlify et nous connecter. Tout d'abord, ajoutons un nouveau site à partir de l'écran Sites. Si c'est la première fois que vous utilisez Netlify, il vous demandera de lui donner l'autorisation de lire les référentiels de votre compte GitHub (ou GitLab ou BitBucket). Sélectionnons le référentiel que nous avons configuré.

( Grand aperçu )

Netlify confirmera la branche que nous voulons utiliser pour les déploiements. Il existe également un emplacement pour indiquer à Netlify ce que nous utilisons pour la tâche de génération qui compile notre site pour la production et le répertoire à consulter.

Nous serons invités à entrer notre commande et notre répertoire de génération. Pour Nuxt, c'est:

  • Commande de construction : génération de fil ou npm run generate
  • Répertoire : dist

Consultez le instructions complètes pour déployer une application Vue sur Netlify pour plus de détails. Maintenant, nous pouvons déployer! ?

Configuration de la boutique

Non, nous n'entrons pas dans le commerce électronique ou quoi que ce soit. Nuxt est équipé de la possibilité d'utiliser un magasin Vuex hors de la porte. Cela fournit un endroit central où nous pouvons stocker des données pour les composants à appeler et à consommer. Vous pouvez y penser comme le «cerveau» de l'application.

Le répertoire / store est vide par défaut. Créons un fichier là-dedans pour commencer à créer un endroit où nous pouvons stocker des données pour la page d'index. Appelons cela de manière créative index.js. Sarah a une extension de code VS avec des raccourcis qui rendent cette configuration assez banale. Avec cela installé (en supposant que vous utilisez VS Code, bien sûr), nous pouvons taper vstore2 et il crache tout ce dont nous avons besoin:

 export const state = () => ({
    valeur: 'mavaleur'
})

exporter les const getters = {
    getterValue: state => {
        return state.value
    }
}

exporter les mutations const = {
    updateValue: (état, charge utile) => {
        state.value = charge utile
    }
}

exporter des actions const = {
    updateActionValue ({commit}) {
        commit ('updateValue', charge utile)
    }
}

Fondamentalement, la configuration est la suivante:

  • l'état contient les messages ou toutes les informations que nous devons stocker.
  • les mutations contiendront des fonctions qui mettront à jour l'état. Les mutations sont la seule chose qui peut mettre à jour l'état les actions ne le peuvent pas.
  • les actions peuvent effectuer des appels d'API asynchrones. Nous allons l'utiliser pour appeler l'API WordPress, puis valider une mutation pour mettre à jour l'état. Tout d'abord, nous allons vérifier s'il y a une longueur dans le tableau des messages dans l'état ce qui signifie que nous avons déjà appelé l'API, donc nous ne le faisons plus.

Tout de suite, nous pouvons supprimer le les getters bloquent parce que nous ne les utiliserons pas pour le moment. Ensuite, nous pouvons remplacer la valeur: « myValue » dans l’état par un tableau vide qui sera réservé pour les données de nos publications: publications: []. C'est là que nous allons conserver toutes nos données! De cette façon, tout composant qui a besoin des données a une place pour les récupérer.

La seule façon dont nous pouvons mettre à jour l'état est avec des mutations, c'est donc là que nous nous dirigeons ensuite. Grâce à l'extrait, tout ce que nous devons faire est de mettre à jour les noms génériques dans le bloc avec quelque chose de plus spécifique à notre état. Donc, au lieu de updateValue allons-y avec updatePosts ; et au lieu de state.value faisons state.posts . Ce que cette mutation fait, c'est prendre une charge utile de données et changer l'état pour utiliser cette charge utile.

Voyons maintenant le bloc d'actions . Les actions sont la manière dont nous pouvons travailler avec des données de manière asynchrone. Les appels asynchrones permettent de récupérer les données de l'API WordPress. Mettons à jour les valeurs passe-partout avec les nôtres:

 / *
c'est là que nous conserverons éventuellement les données de tous nos messages
* /
exporter l'état const = () => ({
    messages: []
})
/ *
cela mettra à jour l'état avec les messages
* /
exporter les mutations const = {
    updatePosts: (état, messages) => {
        state.posts = posts
    }
}
/ *

actions est l'endroit où nous ferons un appel API qui rassemble les messages,
puis valide la mutation pour la mettre à jour
* /
exporter des actions const = {
    // ce sera asynchrone
    getPosts asynchrones ({
        Etat,
        commettre
    }) {
        // la première chose que nous allons faire est de vérifier s'il y a une longueur quelconque dans le tableau des posts, ce qui signifie que nous avons déjà appelé l'API, alors ne recommencez pas.
        si (state.posts.length) retourne
    }
}

Si des erreurs se produisent en cours de route, nous allons détecter ces erreurs et les enregistrer dans la console. Dans les applications de production, nous vérifions également si l'environnement était en cours de développement avant de nous connecter à la console.

Ensuite, dans cette action que nous avons configurée, nous allons essayer d'obtenir les publications de l'API:

 exporter des actions const = {
 async getPosts ({état, validation}) {
   si (state.posts.length) retourne
   essayez {
     laissez les messages = attendre la récupération (`https: //css-tricks.com/wp-json/wp/v2/posts? page = 1 & per_page = 20 & _embed = 1`
     ) .then (res => res.json ())
     posts = messages
       .filter (el => el.status === "publier")
       .map (({id, slug, title, extrait, date, tags, content}) => ({
         id
         limace,
         Titre,
         extrait,
         Date,
         Mots clés,
         contenu
       }))
     commit ("updatePosts", messages)
   } catch (err) {
     console.log (err)
   }
} 

Vous avez peut-être remarqué que nous ne prenons pas seulement toutes les informations et les stockons, nous filtrons uniquement ce dont nous avons besoin. Nous le faisons parce que WordPress stocke en effet une grande quantité de données pour chaque publication, dont certaines seulement pourraient être nécessaires à nos fins. Si vous connaissez les API REST, vous savez peut-être déjà qu'elles renvoient généralement tout. Pour plus d'informations à ce sujet, vous pouvez consulter un excellent article de Sebastian Scholl sur le sujet .

C'est là que la méthode .filter () entre en jeu. Nous pouvons l'utiliser pour récupérer uniquement le schéma dont nous avons besoin, ce qui est une bonne amélioration des performances. Si nous retournons dans notre magasin, nous pouvons filtrer les données dans messages et utiliser .map () pour créer un nouveau tableau de ces données.

Faisons cela pour que nous n'obtenons que des articles publiés (parce que nous ne voulons pas que des brouillons apparaissent dans notre flux), l'ID de l'article (pour faire la distinction entre les articles), le slug de l'article (bon pour relier les articles), le titre de l'article (oui, un peu important) , et l'extrait de message (pour un petit aperçu du contenu), et d'autres choses comme les balises. Nous pouvons supprimer cela dans le bloc try juste avant la validation.

Cela nous donnera des données qui ressemblent à ceci:

 messages: [
 {
   contenu: objet
     protégé: faux
     rendu: "

La ​​typographie fluide est l'idée ..."    date: "2019-11-29T08: 11: 40"    extrait: Object      protégé: faux      rendu: "

La ​​typographie fluide est l'idée ..."    identifiant: 299523    limace: "typographie fluide simplifiée"    tags: tableau [1]      0: 963    titre: objet      rendu: "Typographie fluide simplifiée"    },  … ]

D'accord, nous avons donc créé un tas de fonctions, mais maintenant elles doivent être appelées quelque part afin de rendre les données. Revenons à notre fichier index.vue dans le répertoire / pages pour le faire. Nous pouvons effectuer l'appel dans un bloc de script juste en dessous de notre balisage de modèle.

Rendons-les!

Dans ce cas, nous voulons créer un modèle qui rend une boucle de billets de blog. Vous savez, le genre de page qui affiche les 10 derniers articles. Nous avons déjà le fichier dont nous avons besoin, qui est le fichier index.vue dans le répertoire / pages . Il s'agit du fichier que Nuxt reconnaît comme la «page d'accueil» de l'application. Nous pourrions tout aussi facilement créer un nouveau fichier si nous voulions que le flux de messages soit ailleurs, mais nous l'utilisons car nous avons affaire à un site basé sur un blog. Ouvrons ce fichier, effaçons ce qui est déjà là et déposons notre propre balisage de modèle là-dedans.

Nous enverrons cette action et rendrons les messages:

   
( Grand aperçu )

Dans la méthode de cycle de vie créée vous voyez que nous lançons cette action qui récupérera les publications de l'API. Ensuite, nous stockons les publications que nous obtenons dans une propriété calculée appelée publications . Ensuite, dans le modèle, nous parcourons tous les messages et rendons le titre et l'extrait de chacun, en le reliant à une page de message individuelle pour le message entier (pensez comme single.php ) que nous n'avons pas pas encore construit. Faisons donc cette partie maintenant!

Création dynamique de pages de publication individuelles

Nuxt a un excellent moyen de créer des pages dynamiques, avec un code minimal, vous pouvez configurer un modèle pour toutes vos publications individuelles.

Premièrement, nous devons créer un répertoire et y mettre une page avec un trait de soulignement, en fonction de la façon dont vous le rendrez. Dans notre cas, il s'appellera blog, et nous utiliserons les données de limaces que nous avons importées de l'API, avec un trait de soulignement. Notre répertoire ressemblera alors à ceci:

 index.vue

Blog/

   _slug.vue
 

Nous enverrons la demande getPosts juste au cas où ils entreraient sur le site via l'une des pages individuelles. Nous allons également extraire les données des publications du magasin.

Nous devons également nous assurer que cette page sait à quelle publication nous faisons référence. Pour ce faire, nous devons stocker ce slug particulier avec this. $ Route.params.slug . Ensuite, nous pouvons trouver le message particulier et le stocker en tant que propriété calculée à l'aide du filtre:

 calculé: {
  ...
  Publier() {
    renvoyer this.posts.find (el => el.slug === this.slug);
  }
},
Les données() {
  revenir {
    slug: this. $ route.params.slug
  };
},

Maintenant que nous avons accès à la publication en question, dans le modèle, nous afficherons le titre, ainsi que le contenu. Étant donné que le contenu est une chaîne contenant déjà des éléments HTML que nous voulons utiliser, nous utiliserons la directive vue v-html pour rendre cette sortie.


( Grand aperçu )

La ​​dernière chose que nous devons faire est de faire savoir à Nuxt qu'il doit générer toutes ces routes dynamiques. Dans notre fichier nuxt.config.js, nous informerons nuxt lorsque nous utiliserons la commande generate (qui permet à nuxt de construire statiquement), d'utiliser une fonction pour créer les routes. Nous appellerons notre fonction dynamicRoutes .

 génère: {
  itinéraires: dynamicRoutes
},

Ensuite, nous allons installer axios en exécutant fil add axios en haut du fichier, nous allons l'importer. Ensuite, nous créerons une fonction qui générera un tableau de publications en fonction des limaces que nous récupérons de l'API. Je couvre cela plus en détail dans cet article.

 import axios from "axios"
laissez dynamicRoutes = () => {
retour axios
  .get ("https://css-tricks.com/wp-json/wp/v2/posts?page=1&per_page=20")
  .then (res => {
    return res.data.map (post => `/ blog / $ {post.slug}`)
  })
}

Cela va créer un tableau qui ressemble à ceci:

 export default {
 produire: {
   itinéraires: [
     '/blog/post-title-one',
     '/blog/post-title-two',
     '/blog/post-title-three'
   ]
 }
}

Et c'est parti pour les courses! Maintenant déployons-le et voyons ce que nous avons.

Créez la possibilité de sélectionner via des balises

La dernière chose que nous allons faire est de sélectionner des publications par balise. Cela fonctionne de manière très similaire pour les catégories, et vous pouvez créer toutes sortes de fonctionnalités en fonction de vos données dans WordPress, nous ne montrons ici qu'un chemin possible. Il vaut la peine d'explorer la référence de l'API pour voir tout ce qui est à votre disposition.

Auparavant, lorsque vous rassembliez les données de balises à partir des publications, il vous indiquait le nom des balises. Malheureusement, dans la version 2 de l'API, il vous donne simplement l'ID, vous devez donc effectuer un autre appel d'API pour obtenir les noms réels.

La première chose que nous ferons est de créer un autre plugin rendu par le serveur pour rassembler les balises comme nous l'avons fait avec les messages. De cette façon, il fera tout cela au moment de la construction et sera rendu immédiatement pour l'utilisateur final (yay JAMstack!)

 exportation asynchrone par défaut ({store}) => {
  attendre store.dispatch ("getTags")
}

Ensuite, nous allons créer une action getTags où nous passerons dans les messages. L'appel d'API sera très similaire, mais nous devons passer les balises dans ce format, où après inclure UTM, nous passons les ID, séparés par des virgules, comme ceci:

 https://css-tricks.com/ wp-json / wp / v2 / tags? include = 1,2,3

Pour le formater comme ça, nous devons prendre les messages et extraire tous les identifiants. Nous le ferons avec une méthode .reduce () :

 async getTags ({state, commit}, posts) {
  if (state.tags.length) return
  laissez allTags = posts.reduce ((acc, item) => {
    return acc.concat (item.tags);
  }, [])
  allTags = allTags.join ()
  essayez {
    laisser les balises = attendre la récupération (
      `https://css-tricks.com/wp-json/wp/v2/tags?page=1&per_page=40&include=$ {allTags}`
    ) .then (res => res.json ())
    tags = tags.map (({id, name}) => ({
      id, nom
    }))
    commit ("updateTags", balises)
  } catch (err) {
    console.log (err)
  }
}

Tout comme les articles, nous avons besoin d'un emplacement dans l'état pour stocker les balises et d'une mutation pour les mettre à jour:

 export const state = () => ({
  messages: [],
  tags: []
})

exporter les mutations const = {
  updatePosts: (état, messages) => {
    state.posts = posts
  },
  updateTags: (état, tags) => {
    state.tags = tags
  }
}

Maintenant, dans notre page index.vue, nous pouvons importer les balises du magasin et les afficher toutes

 calculé: {
  Mots clés() {
    retourner ceci. $ store.state.tags;
  },
}


Cela nous donnera cette sortie visuelle:

( Grand aperçu )

Maintenant, c'est très bien, mais nous pourrions vouloir filtrer les messages en fonction de celui que nous avons sélectionné. Heureusement, les propriétés calculées dans Vue ne font que peu d'efforts.

   

Premièrement, nous allons stocker une propriété de données qui nous permet de stocker le selectedTag . Nous allons commencer avec une valeur nulle .

Dans le modèle, lorsque nous cliquons sur la balise, nous exécutons une méthode qui transmettra dans quelle balise elle se trouve, nommée updateTag . Nous l'utiliserons pour définir selectedTag sur l'ID de la balise ou revenir à null, lorsque nous aurons terminé le filtrage.

À partir de là, nous modifierons notre v-for directive qui affiche le message de "poste dans les postes" à "poste dans les messages triés" . Nous allons créer une propriété calculée appelée sortedPosts . Si le selectedTag est défini sur null, nous ne renverrons que tous les messages, mais sinon nous ne retournerons que les messages filtrés par le selectedTag :

   

Maintenant, la dernière chose que nous voulons faire pour peaufiner l'application est de styliser la balise sélectionnée juste un peu différemment et de faire savoir à l'utilisateur que vous pouvez la désélectionner.

   

Et voilà! Tous les avantages d'un système d'édition de contenu riche comme WordPress, avec les avantages de performance et de sécurité de JAMstack. Vous pouvez maintenant découpler la création de contenu de votre pile de développement et utiliser un cadre JavaScript moderne et l'écosystème riche dans votre propre application!

 Bouton Déployer vers Netlify Encore une fois, si vous souhaitez ignorer toutes ces étapes et déployer le modèle directement, en le modifiant selon vos besoins, nous le configurons pour vous. Vous pouvez toujours vous référer ici si vous avez besoin de comprendre comment il est construit.

Il y a quelques choses que nous n'avons pas couvertes qui sortent du cadre de l'article (c'est déjà assez long!)

 Éditorial fracassant (dm, ra, il)




Source link