Files
binome/GUIDE_DEVELOPPEMENT.md
Julien Calixte c433d0d7bf migrate to Vue3
2025-07-21 01:20:57 +02:00

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