-
Notifications
You must be signed in to change notification settings - Fork 0
Documentation Front End
L’objectif de cette documentation est de décrire comment fonctionne l’architecture du projet FrontEnd de Fiches&Chips afin que n’importe quel développeur puisse aborder Nuxt plus facilement. Les principales parties seront :
- Javascript ES6
- Nuxt en général (SSR, Vue)
- Architecture du projet
- Dossier Pages
- Dossier Api
- Store Vuex
- Middleware
- Tailwind
- I18n
Si des erreurs se manifestent dans cette documentation, n’hésitez pas à le signaler.
L’arrivée de Javascript ES6 facilite le développement avec ce même langage. De nombreuses conventions sont disponibles pour gagner du temps lors de l’écriture du code de notre FrontEnd. Il est pertinent de pointer du doigts ces principales conventions avant de discuter autour du framework utilisé. Celles-ci permettront alors à tout le monde d’avoir un code + lisible et même plus performant. On pourrait en parler des heures, si le passage en ES6 vous intéresse vous avez tous les changements à ce lien. Ces points suivants visent à proposer quelques bonnes pratiques. Si vous avez des propositions ou suggestions, n’hésitez surtout pas à le faire remonter ! Si vous souhaitez des bonnes pratiques côté Vue, vous pouvez consulter ce lien ci.
Pour la lisibilité, d’abord regrouper les imports externes aux projets. Après deux sauts de ligne, écrire les imports internes au projet.
Import Vue from ‘vue’
Import i18n from ‘i18n’
Import Modal from ‘~/src/components/common/modal.vue’
Import LoginModal from ‘~/src/components/common/LoginModal.vue’
const firstname = ‘Gabriel’
const lastname = ‘Riboldi’
const age = 25
const user = {
'firstname': firstname,
'lastname': lastname,
'minor': age < 18,
'is-active': true
}
On peut simplifier ca avec les règles suivantes :
- Si la clé et la variable utilisée comme valeur portent le même nom, on peut simplement passer la variable, la clé prendra le même nom
- Pas besoin de quotes lorsque la clé est simple, mais elles restent nécessaires lorsqu’on a des caractères spéciaux (tirets, espaces, etc.)
const firstname = ‘Gabriel’
const lastname = ‘Riboldi’
const user = {
firstname,
lastname,
minor: age < 18,
'is-active': true
}
Privilégier l’utilisation des " ` " pour écrire des chaînes de caractère, particulièrement si elles sont contiennent des variables (que l’on intègrera à la chaîne de caractère avec la syntaxe ${variable}) ou des sauts de ligne.
console.log('Bonjour ' + firstname + ' ' + lastname + ',' + 'Comment vas-tu ?')
Ce que l’on transforme en :
console.log(`Bonjour ${firstname} ${lastname}, comment vas-tu ?`)
Si aucune variable n'est implémentée dans une chaine de caractères, il faut cependant éviter de l'utiliser (inutilement).
Il arrive souvent qu’un objet soit décrit sur plusieurs niveaux de profondeur. Lorsqu’on a besoin de vérifier la valeur d’une propriété située à un niveau de profondeur supérieur à 1 (par exemple response.data.user.active), cela déclenchera une erreur si response.data ou si response.data.user ne sont pas définis. On en vient donc à écrire un long code inutile avec beaucoup de copier/coller.
if (response.data && response.data.user && response.data.user.active) { //traitement }
On peut simplifier cette écriture en naviguant à travers l’objet par l’opérateur ?
.
if (response?.data?.user?.active) { //traitement }
Si un des niveaux n’existe pas, le résultat sera undefined
.
ES6 propose plusieurs options de destructuration d’un object.
Ne pas faire :
const firstname = user.firstname
const lastname = user.lastname
…
Plutôt faire :
const { firstname, lastname } = user
Chaque valeur de l’array est assignée dans l’ordre à une variable.
const [a, b] = [10, 20]
console.log(a, b) // valeur attendue: 10, 20
Les valeurs extraites peuvent être assignées à des variables portant un nom différent de la clé.
const numbers = { val1: 10, val2: 20 }
const { val1: a, val2: b } = numbers
console.log(val1, val2) // valeur attendue: undefined, undefined
console.log(a, b) // valeur attendue: 10, 20
Attention, dans l’exemple ci-dessus, aucune variable n’est déclarée pour val1
et val2
, qui ont donc une valeur undefined
Il existe pleins d’autres conventions. A vous de les ajouter/suggérer/partager si vous en savez !
Nuxt est le fameux framework basé sur Vue.js et Node.js. L'utilisation de ce framework a de nombreux avantages comme l'amélioration des processus de l'optimisation pour les moteurs de recherches du fait du rendu côté serveur (SSR) des pages web avant leur envoi vers le client ce qui n'est pas fait de manière générale dans les applications web monopages. En utilisant Nuxt.js les sites webs peuvent ainsi inclure des interfaces utilisateurs plus complexes tout en gardant les avantages du rendu HTML côté serveur.
Si vous êtes familier avec les framework FrontEnd en Server Side Rendering, vous ne serez pas perdu puisque l’on y retrouve ici de nombreuses conventions telles que le FileSystem Routing, la création d’une simple api (qui marche elle aussi en FileSystem Routing) dans un dossier api
, du HotReloading, un Store style Redux (nommé Vuex) intégré directement au framework, l'auto-import (oui) etc...
Nuxt propose également un système de modules/plugins : des lib directement intégrées au framework.
[WIP]
./Front
├── Dockerfile
├── README.md
├── assets
│ ├── images
│ ├── fonts
│ └── sounds
├── components
│ ├── Modal.vue
│ ├── NuxtLogo.vue
│ ├── Placeholder.vue
│ ├── subComponent
│ │ ├── CustomInput.vue
│ │ ├── CustomTable.vue
│ │ └── Sidebar.vue
│ └── subModals
│ └── exampleModal.vue
├── locales
│ ├── en.json
│ └── fr.json
├── middleware
│ └── index.js
├── nuxt.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── index.vue
├── playwright.config.js
├── static
│ ├── favicon.ico
├── store
│ └── index.js
├── tailwind.config.js
├── tests
│ └── example.spec.js
├── tsconfig.json
└── yarn.lock
Architecture d'un framework SSR assez classique :
-
Dossier Assets : Tous les assets.
- images : Les images utilisées sur la plateforme.
- fonts : Les fonts utilisées sur la plateforme.
- sounds : Les sons utilisés sur la plateforme.
-
Dossier Components : Tous les composants voués à être réutilisés plusieurs fois.
- subComponents : Les Composants génériques, utilisés un peu partout (Input, Button...)
- subModals : Le contenu de différentes modales, héritant du design de base d'une modale (Bouton fermer, background...)
- Les composants principaux
-
Dossier Locales : Tous les fichiers de traduction sous forme de .json.
- locale.fr : Traductions françaises (langue par défaut).
- locale.en : Traductions anglaises.
(Il est tout à fait possible de rajouter d'autres fichiers locale.* pour d'autres traductions)
-
Dossier Middleware : Tous les Middleware.
-
Dossier Pages : Toutes les Pages/Routes.
A chaque fois qu'un fichier ou un dossier est créé dans ./pages
, une route est ajoutée au serveur.
├── pages
├── index.vue ( https://www.fichesetchips.com/ )
├── about.vue ( https://www.fichesetchips.com/about
user
[id]
├── dashboard.vue ( https://www.fichesetchips.com/user/[id]/dashboard )
Dans un dossier, on peut rajouter un index.js pour la route par défaut d'un dossier (elle prendra le nom du dossier), ou une valeur entre []
pour une valeur dynamique envoyée en query dans la requete.
Il est aussi possible de créer un dossier api
dans notre dossier Pages
afin de créer des routes pour une api. La syntaxe sera la même qu'un serveur express classique.
-
Dossier Static : Fichiers public vouant à ne pas être modifiés.
-
Dossier Layouts : Layouts utilisés pour les différentes pages.
En quelques mots, un Layout c'est une base (design) que l'on va répéter sur plusieurs pages. Au lieu de dupliquer un design sur différentes pages, on utilise un Layout qui va hériter des composants enfants (le contenu de notre page). Par exemple, on peut utiliser un Layout pour définir une font utilisée ou une couleur de background par défaut dans une page.
Par défaut, le dossier n'est pas créé. On peut le créer à la root du projet, dans lequel nous allons mettre nos fichiers [NomDuLayout].vue pour chaque Layout.
Petit plus : On peut créer un Layout default.vue
, qui sera un Layout que l'on utilisera par défaut sur toutes nos Vues !
Comment écrire notre code pour un Layout :
// La classique balise `<template />`, avec le composant `<Nuxt />`
// qui représente le contenu de votre page (les enfants dudit Layout).
<template>
<Nuxt />
</template>
Voilà ! Vous pouvez encapsuler cette balise <Nuxt />
avec d'autres composants ...
<template>
<div>
<TheHeader />
<Nuxt />
<TheFooter />
</div>
</template>
N'oubliez pas que Tailwind est utilisable dans ces Layouts !
- Dossier Store : Fichiers permettant la gestion du Store Vuex intégré à la plateforme (il est par défaut désactivé).
Tailwind CSS est un framework CSS avec des classes prédéfinies que vous pouvez utiliser pour construire et concevoir des pages web directement dans votre balisage HTML. Cela a l'avantage de ne compiler qu'avec les classes CSS que vous utilisez, ce qui vous évite de vous retrouver avec une web app' comportant 20.000 lignes de CSS (Coucou Bootstrap).
// Exemple d'utilisation de Tailwind pour un Input générique. Merci Havane !
<div class="flex flex-col m-5">
<label v-if="label" for="">
{{ label }}
</label>
<input
class="w-full h-12 p-3 border placeholder-gray-700 shadow-inner outline-none placeholder-opacity-50"
:placeholder="placeHolder"
type="text"
/>
</div>
Certains n'aiment pas Tailwind à cause du fait que cumuler les class dans une balise rend potentiellement la lecture indigeste (ce qui est un avis tout à fait fondé). Chacun son école, il n'y a pas de vérité absolue.
Nuxt possède un module Tailwind afin d'intégrer facilement la librairie au framework. Après quelques configurations dans le plugin pour purge le server des class CSS que l'on utilise pas...
// Fichier tailwind.config.js
[...]
module.exports = {
mode: 'jit',
purge: ['./public/**/*.html', './src/**/*.{js,jsx,ts,tsx,vue}'],
content: [
'./components/*.{js,vue,ts}',
'./layouts/*.vue',
'./pages/*.vue',
'./plugins/*.{js,ts}',
'./nuxt.config.{js,ts}',
],
theme: { ...
[...]
On arrive à un temps de compilation avec un framework CSS tout à fait honorable ...:
Toutes les classes Tailwind sont disponibles à ce lien. Elles ressemblent fortement aux keywords classiques du CSS. Par exemple, pour un margin horizontal:
// Margin horizontal de 1 rem : mx-4 (soit margin-left: 1rem; margin-right: 1rem;)
<div className="mx-4">
<p>Coucou la doc !</p>
</div>
On parle ici de margin
, mais on peut très bien mettre un texte en Bold, aligner les éléments verticalement, mettre une ombre portée rouge ... ou même créer ses propres couleurs ! Pratique pour définir la palette de couleur d'une plateforme web. Tout se passe dans le fichier tailwind.config.js
:
// tailwind.config.js
[...]
theme: {
extend: {
colors: {
'fiche-green': '#4FEA74',
'chips-yellow': '#FFDB57',
},
},
},
[...]
On a créé deux couleurs grace à 2 valeurs hexadecimales : fiche-green
et chips-yellow
. Ces couleurs peuvent ensuite être utilisées dans nos balises HTML :
// On peut l'utiliser avec le keyword "text" pour "texte" de Tailwind
<p className="text-fiche-green">
Trop génial omg
</p>
// On peut aussi l'utiliser avec le keyword "bg" pour "background" de Tailwind
<div className="bg-fiche-green">
[... Contenu de ma div mais en vert ...]
</div>
L'utilisation est multiple. De notre côté pour Fiches&Chips, pour que la palette reste lisible, nous définissons la couleur de cette manière :
// `fc` pour Fiches&Chips
fc-<couleur>
fc-red
i18n Nuxt est une librairie permettant la traduction de tous les textes d'une application Web.
Cela fonctionne à l'aide de fichiers .json que l'on va remplir avec une key
+ une valeur
. Quand une key
est rencontrée parmis le texte mentionné dans le code, ce texte est remplacé par une autre valeur en fonction de l'actuelle locale
définie dans le front. Par exemple, notre locale par défaut est fr
. Si l'on passe en locale en
(anglais) à l'aide d'un i18n Switcher
, nos textes passerons en locale en
, donc avec les valeurs de notre fichier en.json
.
Après quelques configurations dans le fichier nuxt.config.js
...
i18n: {
locales: ['fr', 'en'],
defaultLocale: 'fr',
vueI18n: {
fallbackLocale: 'fr',
messages: {
en,
fr,
},
},
},
... nous n'avons qu'à remplir la locale de notre choix :
// Fichier `en.json`
{
"Nom d'utilisateur": "Username",
"Mot de passe": "Password"
}
Enfin, pour appeler l'utilaire de traduction dans le front qui va nous permettre d'aller chercher une valeur
selon une key
:
// Traduction avec la key `Nom d'utilisateur`
<p>
{{ $t("Nom d'utilisateur") }}
</p>
// Ce qui affichera la valeur de la key, soit "Nom d'utilisateur" en locale fr, ou "Username" en locale en