Organiser un projet Vue.js modulaire
Quand on découvre Vue.js, il est tentant de tout écrire dans un seul fichier. On commence avec createApp(), quelques données, des méthodes, un ou deux composants globaux. C’est simple, rapide, lisible… au début. Mais très vite, les blocs se multiplient, les interactions se croisent, et on perd en clarté. Ce n’est pas une question de complexité technique, mais de lisibilité.
Organiser un projet Vue.js ne signifie pas le rendre plus abstrait. Il s’agit simplement de structurer ce que l’on a déjà appris, en séparant le code dans des fichiers dédiés, en regroupant les composants dans un dossier commun, en gardant une logique modulaire — même sans outil de compilation.
Dans cet article, nous allons voir comment passer d’un fichier monolithique à une structure plus claire. Ce n’est pas une refonte, juste un réagencement progressif. Nous le ferons en suivant le fil de notre application vidéo, mais les principes s’appliquent à tous les projets Vue.js — quels que soient leur taille, leur sujet, ou leur niveau de sophistication.
Pourquoi découper un projet Vue.js ?
Au départ, tout tient dans un seul fichier. On y initialise Vue.createApp(), on y déclare les data(), les methods, les computed, les watch, et même les composants globaux. Tout fonctionne, mais très vite, ce fichier devient trop chargé.
On scrolle, on cherche, on commente, on oublie. Chaque ajout rend le fichier plus long, plus fragile, moins lisible. Le code fonctionne encore, mais on ne sait plus exactement qui fait quoi, ni où modifier sans risquer de tout casser.
En réalité, Vue.js n’impose aucun découpage. Mais dès qu’un projet devient un peu plus riche — plusieurs composants, une interface dynamique, une logique de formulaire, un filtrage — le besoin d’organisation devient naturel.
Découper un projet, ce n’est pas complexifier le code. C’est l’inverse : c’est permettre de mieux le lire, mieux le maintenir, mieux le faire évoluer. Et cela peut se faire très simplement, sans outil, sans build, sans migration. Un dossier components/, quelques fichiers bien nommés, et une structure lisible suffisent déjà à transformer l’expérience.
Créer un dossier components/
Le premier pas vers une organisation modulaire, c’est de créer un dossier components/ à la racine du projet. On y place chaque composant dans un fichier séparé, avec un nom clair, souvent en PascalCase (ex. Lightbox.js, VideoLightbox.js, ArtistModal.js). Chaque fichier contient la définition complète du composant : son template, ses props, ses éventuels événements émis, et ses styles si besoin.
Prenons un exemple très simple. Voici le fichier Lightbox.js :
export default {
name: 'Lightbox',
props: ['src', 'visible'],
emits: ['close'],
template: `
<div v-if="visible" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50">
<div class="relative">
<img :src="src" class="max-w-full max-h-full">
<button @click="$emit('close')" class="absolute top-2 right-2 text-white text-2xl">×</button>
</div>
</div>
`
};Ce composant est désormais isolé dans son propre fichier. Il n’encombre plus le fichier principal, et il devient facile à réutiliser, à modifier, ou à supprimer si besoin.
Ce découpage est aussi l’occasion d’adopter une logique claire : un fichier = un composant = une responsabilité. Ce n’est pas seulement une habitude de développement moderne, c’est un vrai confort dès qu’on revient sur le code après quelques jours.
Créer un composant VideoLightbox
Dans une approche modulaire, chaque élément structurant de l’interface mérite son propre fichier. Si une vidéo s’affiche dans une modale distincte, avec des comportements dédiés, autant isoler ce composant dans un fichier VideoLightbox.js.

Comme pour Lightbox, ce fichier exporte un objet unique, structuré autour des propriétés name, props, emits et template. En séparant ce bloc de code, on garde un fichier principal plus lisible, tout en facilitant la maintenance.
Ce composant peut maintenant être importé où bon vous semble, sans duplication ni pollution globale. Il devient un bloc réutilisable, clair, indépendant, prêt à évoluer.
Intégrer les composants dans le fichier principal
Une fois nos composants bien définis dans des fichiers séparés, il faut les importer et les enregistrer dans l’application principale. Cela se fait directement dans le fichier où createApp() est utilisé — souvent main.js, app.js ou index.js, selon votre organisation.
Reprenons le cas des deux composants précédents :
import { createApp } from 'vue';
import App from './App.vue';
import Lightbox from './components/Lightbox.js';
import VideoLightbox from './components/VideoLightbox.js';
const app = createApp(App);
app.component('lightbox', Lightbox);
app.component('video-lightbox', VideoLightbox);
app.mount('#app');Cette structure fait trois choses essentielles :
- Elle importe les composants depuis leur dossier (
./components/...). - Elle les enregistre globalement via
app.component(...)pour les rendre utilisables dans tous les fichiers de template. - Elle monte l’application à partir d’un composant racine (
App.vueou équivalent).
Si vous utilisez encore un modèle “HTML externe + script Vue” sans App.vue, vous pouvez garder la même logique :
import Lightbox from './components/Lightbox.js';
import VideoLightbox from './components/VideoLightbox.js';
const app = Vue.createApp({ /* données, computed, methods... */ });
app.component('lightbox', Lightbox);
app.component('video-lightbox', VideoLightbox);
app.mount('#app');L’important ici est de centraliser l’enregistrement des composants dans un seul point d’entrée, ce qui permet de maîtriser l’architecture de l’application et d’en faciliter le débogage ou l’extension.
Souhaitez-vous enchaîner avec le chapitre sur les Single File Components (.vue), ou rester dans la structure JS classique pour encore un chapitre ?
Structurer les styles et les assets
Une application bien organisée ne concerne pas que les composants JavaScript. Les feuilles de style, les images, les polices ou les fichiers SVG méritent aussi une place claire. Sans cela, le dossier principal devient vite illisible.
Commencez par créer des sous-dossiers explicites : css/, img/, fonts/, icons/, selon vos besoins. Cela permet de garder une vue d’ensemble tout en isolant les fichiers liés à l’apparence ou aux médias.
```
/project-root
├── index.html
├── css
│ ├── app.css
│ └── lightbox.css
├── img
│ └── close-icon.svg
├── js
│ ├── app.js
│ └── components
│ └── Lightbox.js
```Si vous utilisez plusieurs fichiers CSS, privilégiez des noms compréhensibles : app.css pour la structure globale, form.css pour les styles de formulaire, modal.css pour les fenêtres contextuelles… Vous pourrez ensuite les regrouper dans un index.css ou les charger individuellement dans le <head>.
Même en développement sans outil de compilation, avec des <script type="module">, vous pouvez garder une approche modulaire. Par exemple, un composant peut appeler une petite feuille de style dédiée (avec <link> ou @import) si son usage est très spécifique. L’important est de ne pas mélanger tous les styles dans un seul fichier géant.
Enfin, côté médias, évitez les noms de fichiers ambigus : photo1.jpg n’aide personne à comprendre ce qu’il représente. Préférez logo-association.svg, background-home.jpg ou icon-play.png. Ce sont de petits choix qui font une grande différence à long terme.
Utiliser des fichiers .vue (Single File Components)
Lorsque le projet commence à grandir, maintenir tous les composants dans des fichiers .js peut devenir fastidieux. Vue.js propose une solution élégante : les Single File Components (ou fichiers .vue), dans lesquels chaque composant est structuré en trois parties distinctes : template, script et style.
Prenons un exemple avec notre composant Lightbox.vue :
<!-- Fichier : Lightbox.vue -->
<template>
<div v-if="visible" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50">
<div class="relative">
<img :src="src" class="max-w-full max-h-full">
<button @click="$emit('close')" class="absolute top-2 right-2 text-white text-2xl">×</button>
</div>
</div>
</template>
<script>
export default {
name: 'Lightbox',
props: ['src', 'visible'],
emits: ['close']
};
</script>
<style scoped>
/* Styles spécifiques à ce composant */
</style>Avec ce format, le HTML, le JavaScript et le CSS sont regroupés dans un même fichier, mais bien séparés. Cela facilite :
- la lecture du composant,
- sa réutilisation dans d’autres projets,
- l’auto-complétion dans les éditeurs modernes (comme VS Code).
Pour que cela fonctionne, il faut cependant un environnement de build (comme Vite, Webpack ou Vue CLI), car les fichiers .vue doivent être compilés avant d’être compris par le navigateur.
Et si l’on voulait aller plus loin ?
Cette organisation fonctionne parfaitement sans outils supplémentaires. Mais si l’on souhaite travailler avec des fichiers .vue complets, ou bénéficier d’une compilation automatique et d’une interface plus dynamique, il est aussi possible d’utiliser un environnement comme Vite ou Vue CLI. Nous resterons pour l’instant sur une structure simple et modulaire, sans prérequis techniques supplémentaires. Un article dédié vous proposera bientôt une prise en main progressive de ces outils.
Importer un composant local dans son script
Une fois notre fichier placé dans le dossier components/, il ne reste plus qu’à l’utiliser dans notre script principal. Pour cela, nous devons l’importer en haut du fichier, puis l’enregistrer localement dans l’option components.
Par exemple, pour utiliser notre VideoLightbox.js, nous écrivons :
import VideoLightbox from './components/VideoLightbox.js';
export default {
components: {
VideoLightbox
},
// … autres options
}Vue saura alors que nous avons le droit d’utiliser <video-lightbox> dans le template de ce fichier. Cela permet de réserver ce composant à une zone spécifique de l’interface, sans l’ajouter à l’ensemble du projet. C’est une manière de garder les composants bien rangés, visibles là où ils sont utiles, mais invisibles ailleurs.
Structurer ses composants dans des sous-dossiers
Dès que le nombre de composants augmente, il devient utile de les regrouper par fonction ou par usage. Cela rend le projet plus lisible, surtout quand on le partage avec d’autres développeurs — ou simplement quand on y revient plusieurs semaines plus tard.
Par exemple, on peut créer des sous-dossiers dans components/ pour organiser ses fichiers :
components/
├── cards/
│ └── VideoCard.js
├── modals/
│ ├── Lightbox.js
│ └── VideoLightbox.js
└── forms/
└── LoginForm.jsAvec cette structure, nos fichiers sont mieux identifiés. On comprend rapidement ce que chaque composant fait, et où le trouver. Cela facilite aussi les imports, qui deviennent explicites :
import VideoCard from './components/cards/VideoCard.js';
import VideoLightbox from './components/modals/VideoLightbox.js';Vue.js ne demande pas de structure particulière. Mais adopter une organisation claire dès le début évite bien des confusions plus tard. Une règle simple : un composant, un fichier, bien nommé et bien rangé.
Correspondance entre noms de fichiers et balises de composants
Quand on importe un composant nommé VideoCard, on peut l’utiliser dans le HTML sous la forme <video-card>. Vue.js transforme automatiquement le nom en kebab-case (avec des tirets), ce qui respecte la syntaxe HTML standard. Par exemple :
import VideoCard from './components/cards/VideoCard.js';devient :
<video-card :video="item" />Cela peut surprendre au début, surtout si l’on vient de JavaScript pur, mais c’est une convention importante. Elle permet d’éviter les conflits avec les balises HTML natives, tout en conservant une syntaxe lisible.
Il est aussi possible d’écrire <VideoCard> avec une majuscule, mais cela ne fonctionnera pas toujours dans un fichier HTML pur. Nous recommandons de toujours utiliser la forme kebab-case dans le HTML, et la forme PascalCase (NomComposant) dans les fichiers JS.
Cela implique donc de soigner la cohérence des noms : un composant appelé ArtistModal sera référencé dans le code HTML comme <artist-modal>. Plus les noms sont explicites et uniformes, plus le code est facile à lire, même des mois plus tard.
Gérer des composants plus complexes
Au fil du temps, un composant simple peut gagner en complexité. On commence par quelques balises HTML, puis on ajoute des props, des emits, des watchers, des effets conditionnels, et parfois d’autres composants imbriqués. Il devient alors essentiel de structurer et commenter ce composant pour en préserver la lisibilité.
Dans un composant comme VideoLightbox, on pourrait imaginer ajouter un système de chapitrage, des métadonnées, des boutons de partage… Ces éléments pourraient eux-mêmes devenir des sous-composants (ChapterList, ShareButton, VideoMeta) pour éviter un fichier trop long et rigide.
Penser dès le départ que chaque composant peut évoluer permet de garder une structure souple, où l’on peut extraire des morceaux sans tout casser. Cette approche favorise aussi la réutilisation, la testabilité et la collaboration si le projet s’élargit.
Conclusion
Organiser son projet, ce n’est pas le complexifier, c’est le rendre lisible, maintenable et évolutif. Une arborescence claire, des composants bien nommés, des fichiers séparés : tout cela ne prend que quelques minutes à mettre en place, mais évite des heures de confusion plus tard.
Avec Vue.js, on peut structurer progressivement, sans outil de build, en HTML natif ou avec des .vue. On commence petit, puis on découpe dès que l’interface s’enrichit. L’important, c’est de penser modulaire dès le départ, même dans un projet simple.
Chaque composant devient alors une brique réutilisable, testable, et compréhensible — par vous-même, ou par une autre personne qui lira votre code dans six mois.
