12 KiB
12 KiB
Guide de Développement - Application Binôme (Stack Moderne)
🚀 Vue d'Ensemble
L'application Binôme est maintenant basée sur une stack moderne Vue 3 + Vite + Pinia, optimisée pour le développement et la performance.
Stack Technique
- Frontend : Vue 3.5.17 + TypeScript
- Build Tool : Vite 7.0.5
- State Management : Pinia 3.0.3 avec persistence
- Routing : Vue Router 4.5.1
- Styling : SCSS avec variables globales
- PWA : vite-plugin-pwa
- Package Manager : pnpm
- Node.js : v20 (LTS)
🛠️ Prérequis et Installation
Prérequis Système
# Node.js version 20 (LTS)
node --version # doit afficher v20.x.x
# pnpm installé globalement
npm install -g pnpm@latest
Installation du Projet
# Cloner le projet
git clone <repository-url>
cd binome
# Installer les dépendances
pnpm install
# Vérifier l'installation
pnpm dev
📜 Scripts Disponibles
Scripts de Développement
# Démarrer le serveur de développement
pnpm dev
# → Lance Vite dev server sur http://localhost:8080
# → Hot Module Replacement (HMR) activé
# → Ouverture automatique du navigateur
# Prévisualiser la build de production
pnpm preview
# → Sert la version buildée localement
# → Utile pour tester avant déploiement
Scripts de Build
# Build de production
pnpm build
# → Génère le dossier /dist optimisé
# → Minification et tree-shaking automatiques
# → Source maps incluses
# Analyser la build
pnpm build --analyze
# → Affiche la taille des bundles
# → Identifie les dépendances lourdes
Scripts de Qualité
# Linter ESLint
pnpm lint
# → Vérifie et corrige automatiquement le code
# → Supporte .vue, .ts, .js files
# → Configuration dans .eslintrc.js
# Type checking TypeScript
pnpm type-check
# → Vérifie les types sans compilation
# → Utile en CI/CD
🏗️ Architecture du Projet
Structure des Dossiers
src/
├── assets/ # Ressources statiques (SVG, images)
├── components/ # Composants Vue réutilisables
│ ├── ChilledMusic.vue
│ ├── DevSession.vue
│ ├── IntervalInput.vue
│ ├── SpotifyMusic.vue
│ ├── SWNewVersion.vue
│ └── ZoneMusic.vue
├── hooks/ # Composables Vue 3
│ ├── useInterval.ts
│ ├── useMusic.ts
│ ├── useSpotify.ts
│ ├── useTimer.ts
│ └── useWakeLock.ts
├── lib/ # Bibliothèques externes
│ └── spotify-player.js # ⚠️ CRITIQUE - Ne pas modifier
├── locales/ # Fichiers de traduction i18n
│ ├── en.json
│ └── fr.json
├── router/ # Configuration Vue Router
│ └── index.ts
├── store/ # Store Pinia
│ └── index.ts
├── styles/ # Styles SCSS globaux
│ ├── app.scss
│ ├── plume.scss
│ └── variables.scss
├── types/ # Types TypeScript
│ └── StopwatchState.ts
├── utils/ # Utilitaires
│ ├── notification.ts
│ └── spotify.ts
├── views/ # Pages/Vues principales
│ ├── Home.vue
│ ├── Privacy.vue
│ └── SpotifyCallback.vue
├── App.vue # Composant racine
├── i18n.ts # Configuration internationalisation
└── main.ts # Point d'entrée de l'application
🎯 Patterns de Développement
1. Composants Vue 3
Composition API avec <script setup>
<template>
<div class="my-component">
<h2>{{ title }}</h2>
<button @click="increment">Count: {{ count }}</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// Props avec TypeScript
interface Props {
title: string
initialCount?: number
}
const props = withDefaults(defineProps<Props>(), {
initialCount: 0
})
// État réactif
const count = ref(props.initialCount)
// Méthodes
const increment = () => {
count.value++
}
// Émissions d'événements
const emit = defineEmits<{
countChanged: [value: number]
}>()
// Watcher
watch(count, (newValue) => {
emit('countChanged', newValue)
})
</script>
<style lang="scss" scoped>
.my-component {
padding: 1rem;
border: 1px solid $primary-color; // Variable SCSS globale
}
</style>
Composables (Hooks Personnalisés)
// hooks/useCounter.ts
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const increment = () => count.value++
const decrement = () => count.value--
const reset = () => count.value = initialValue
const isEven = computed(() => count.value % 2 === 0)
return {
count: readonly(count),
increment,
decrement,
reset,
isEven
}
}
2. Store Pinia
Définition du Store
// store/modules/timer.ts
import { defineStore } from 'pinia'
interface TimerState {
currentTime: number
isRunning: boolean
interval: number
}
export const useTimerStore = defineStore('timer', {
state: (): TimerState => ({
currentTime: 0,
isRunning: false,
interval: 5
}),
getters: {
formattedTime: (state) => {
const minutes = Math.floor(state.currentTime / 60)
const seconds = state.currentTime % 60
return `${minutes}:${seconds.toString().padStart(2, '0')}`
}
},
actions: {
startTimer() {
this.isRunning = true
},
stopTimer() {
this.isRunning = false
},
resetTimer() {
this.currentTime = 0
this.isRunning = false
}
},
// Persistence automatique
persist: {
key: 'timer-store',
storage: localStorage,
paths: ['interval'] // Seuls certains champs
}
})
Utilisation dans les Composants
<script setup lang="ts">
import { useTimerStore } from '@/store'
const timerStore = useTimerStore()
// Accès direct aux propriétés réactives
const { currentTime, isRunning, formattedTime } = storeToRefs(timerStore)
// Accès aux actions
const { startTimer, stopTimer, resetTimer } = timerStore
</script>
3. Internationalisation (i18n)
Utilisation dans les Composants
<template>
<div>
<h1>{{ $t('welcome.title') }}</h1>
<p>{{ $t('welcome.message', { name: userName }) }}</p>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
// Changement de langue
const switchLanguage = (lang: string) => {
locale.value = lang
}
</script>
Ajout de Nouvelles Traductions
// locales/fr.json
{
"welcome": {
"title": "Bienvenue dans Binôme",
"message": "Bonjour {name}, prêt pour une session de programmation ?"
}
}
🎨 Styling et Thèmes
Variables SCSS Globales
// styles/variables.scss
$primary-color: #f8efba;
$secondary-color: #333;
$font-family: 'Arial', sans-serif;
$border-radius: 8px;
$spacing-unit: 1rem;
// Breakpoints
$mobile: 768px;
$tablet: 1024px;
$desktop: 1200px;
Utilisation dans les Composants
<style lang="scss" scoped>
.component {
background-color: $primary-color;
padding: $spacing-unit;
border-radius: $border-radius;
@media (max-width: $mobile) {
padding: $spacing-unit / 2;
}
}
</style>
🔧 Configuration de Développement
Vite Configuration (vite.config.ts)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [
vue(),
VitePWA({
registerType: 'autoUpdate',
workbox: {
skipWaiting: true,
clientsClaim: true
}
})
],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
server: {
port: 8080,
open: true,
hmr: true
}
})
TypeScript Configuration
// tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"paths": {
"@/*": ["src/*"]
}
}
}
🧪 Tests et Qualité
ESLint Configuration
// .eslintrc.js
module.exports = {
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/typescript/recommended'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}
Commandes de Vérification
# Vérification complète avant commit
pnpm lint && pnpm type-check && pnpm build
📱 PWA et Service Worker
Configuration PWA
L'application est configurée comme PWA avec :
- Manifest : Icônes, couleurs, mode d'affichage
- Service Worker : Cache automatique, mise à jour en arrière-plan
- Raccourcis : Accès rapide aux fonctionnalités
Gestion des Mises à Jour
<!-- components/SWNewVersion.vue -->
<template>
<div v-if="needRefresh" class="update-banner">
<p>{{ $t('notification.update.body') }}</p>
<button @click="updateSW">{{ $t('update') }}</button>
</div>
</template>
<script setup lang="ts">
import { useRegisterSW } from 'virtual:pwa-register/vue'
const { needRefresh, updateServiceWorker } = useRegisterSW()
const updateSW = async () => {
await updateServiceWorker()
}
</script>
🎵 Intégration Spotify
Fichier Critique : spotify-player.js
⚠️ ATTENTION : Ce fichier ne doit JAMAIS être modifié
- Contient le SDK Spotify personnalisé
- 571 lignes de code critique
- Toute modification peut casser l'intégration Spotify
Utilisation du Player Spotify
// hooks/useSpotify.ts
import { ref } from 'vue'
export function useSpotify() {
const player = ref<any>(null)
const isReady = ref(false)
const initializePlayer = (token: string) => {
// Utilisation du spotify-player.js
player.value = new window.Spotify.Player({
name: 'Binôme Player',
getOAuthToken: (cb: (token: string) => void) => {
cb(token)
}
})
}
return {
player,
isReady,
initializePlayer
}
}
🚀 Déploiement
Build de Production
# Génération des fichiers optimisés
pnpm build
# Vérification de la build
pnpm preview
Netlify (Configuration dans netlify.toml)
[build]
command = "pnpm build"
publish = "dist"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Variables d'Environnement
# .env.local (non versionné)
VITE_SPOTIFY_CLIENT_ID=your_client_id
VITE_API_BASE_URL=https://api.example.com
🐛 Debugging et Outils
Vue DevTools
- Extension navigateur pour Vue 3
- Inspection des composants et du store Pinia
- Timeline des événements
Vite DevTools
- HMR (Hot Module Replacement)
- Source maps automatiques
- Inspection des modules
Console de Debug
// Activation du debug en développement
if (import.meta.env.DEV) {
console.log('Mode développement activé')
// Exposition du store pour debug
window.__PINIA__ = pinia
}
📚 Ressources et Documentation
Documentation Officielle
Outils Recommandés
- IDE : VS Code avec extensions Vue
- Extensions : Vetur, TypeScript Vue Plugin
- Browser : Chrome/Firefox avec Vue DevTools
🔄 Workflow de Développement
1. Démarrage d'une Nouvelle Fonctionnalité
# Créer une branche
git checkout -b feature/nouvelle-fonctionnalite
# Démarrer le serveur de dev
pnpm dev
2. Développement
- Modifier les fichiers dans
src/ - Tester en temps réel avec HMR
- Utiliser Vue DevTools pour debug
3. Tests et Validation
# Vérification du code
pnpm lint
# Build de test
pnpm build && pnpm preview
4. Commit et Push
# Commit avec message descriptif
git add .
git commit -m "feat: ajout de la nouvelle fonctionnalité"
git push origin feature/nouvelle-fonctionnalite
Guide créé le 20 juillet 2025
Version de l'application : Stack moderne Vue 3 + Vite + Pinia
Prochaine mise à jour : Après résolution des problèmes techniques identifiés