📚 Cours SCSS (Sass) 📍 Chapitre 7 / 21

Gestion des modules avec @use et @forward

Dans le chapitre précédent, nous avons vu comment découper le code avec des partials en utilisant @import. SCSS propose aujourd'hui une gestion moderne des modules grâce à @use et @forward, qui remplacent progressivement @import. Ce chapitre explique pourquoi cette nouvelle approche est meilleure et comment l'utiliser correctement pour créer du code plus robuste, maintenable et professionnel.

Objectifs du chapitre

  • Comprendre les limites de @import et pourquoi il est déprécié.
  • Maîtriser @use pour importer des modules avec namespace.
  • Utiliser @forward pour créer des APIs SCSS propres.
  • Gérer les namespaces pour éviter les conflits de noms.
  • Migrer progressivement de @import vers @use.
À retenir

@use charge un module une seule fois et impose un namespace. Cela rend le code plus prévisible, plus sûr et plus facile à maintenir. C'est la méthode recommandée pour tous les nouveaux projets SCSS.

Explications théoriques détaillées

Pourquoi @import n'est plus recommandé ?

@import fonctionne en injectant simplement le contenu des fichiers les uns dans les autres. Cette approche simpliste entraîne plusieurs problèmes sur des projets complexes :

  • Effet "global" : toutes les variables, mixins et fonctions sont accessibles partout, créant des dépendances cachées.
  • Risque de collisions de noms : si deux fichiers définissent une variable $primary, la dernière écrase la première.
  • Chargements multiples : le même fichier peut être importé plusieurs fois, générant des doublons.
  • Difficulté à raisonner : il est difficile de savoir d'où vient une variable ou un mixin.
  • Ordre des imports critique : un mauvais ordre peut provoquer des erreurs subtiles.
Conseil terrain

Sur des projets complexes, @import rend le SCSS difficile à raisonner et à maintenir. @use impose une discipline salutaire en isolant chaque module dans son propre namespace. Même si @import fonctionne encore, il est officiellement déprécié depuis Dart Sass 1.23.0.

Principe de @use : les modules namespacés

@use importe un fichier SCSS comme un module autonome. Tout ce qui est défini dans ce module (variables, mixins, fonctions) est accessible via un namespace.

SCSS
// Importation d'un module
@use 'variables';

// Utilisation avec namespace
.button {
  background: variables.$primary;
  color: variables.$text-light;
  border-radius: variables.$radius-sm;
}

Ici, $primary n'est accessible que via variables.$primary. Le namespace par défaut est le nom du fichier (sans l'underscore et l'extension).

Principe de @forward : réexposition contrôlée

@forward sert à réexposer des variables, mixins ou fonctions depuis un fichier "index" (ou fichier d'assemblage). Il permet de créer une API claire et contrôlée pour ton SCSS.

SCSS
// Dans _index.scss
@forward 'colors';    // Réexpose tout de _colors.scss
@forward 'spacing';   // Réexpose tout de _spacing.scss
@forward 'typography' hide $font-weights; // Cache certaines variables

@forward ne rend pas le contenu disponible dans le fichier courant, il le rend seulement disponible aux fichiers qui importeront ce fichier via @use.

Exemples simples

Exemple 1 : Utilisation simple de @use

Commençons par un exemple basique pour comprendre la syntaxe.

_variables.scss :

SCSS
// Variables de design
$primary: #3b82f6;
$secondary: #8b5cf6;
$success: #10b981;
$radius-sm: 8px;
$radius-md: 12px;
$radius-lg: 16px;

main.scss :

SCSS
// Importation du module variables
@use 'variables';

// Utilisation avec namespace
.card {
  background: white;
  border-radius: variables.$radius-md;
  border: 1px solid rgba(variables.$primary, 0.2);
  
  .card-title {
    color: variables.$primary;
    margin-bottom: 16px;
  }
  
  .card-button {
    background: variables.$primary;
    color: white;
    padding: 10px 20px;
    border-radius: variables.$radius-sm;
    
    &:hover {
      background: darken(variables.$primary, 10%);
    }
  }
}

CSS généré :

CSS
.card {
  background: white;
  border-radius: 12px;
  border: 1px solid rgba(59, 130, 246, 0.2);
}

.card .card-title {
  color: #3b82f6;
  margin-bottom: 16px;
}

.card .card-button {
  background: #3b82f6;
  color: white;
  padding: 10px 20px;
  border-radius: 8px;
}

.card .card-button:hover {
  background: #2563eb;
}

Exemple 2 : Renommer le namespace avec as

Pour éviter des noms trop longs ou en cas de conflit, on peut renommer le namespace.

SCSS
// Import avec alias
@use 'variables' as v;
@use 'components/buttons' as btn;

.button {
  background: v.$primary;
  padding: btn.$padding-sm btn.$padding-md;
  border-radius: btn.$radius;
}

// Import sans namespace (rare, à utiliser avec précaution)
@use 'utilities' as *;

.element {
  margin: $spacing-md; // Pas de namespace nécessaire
}
À retenir

Le renommage améliore la lisibilité, surtout avec plusieurs modules. L'import sans namespace (as *) est pratique mais doit être utilisé avec parcimonie car il réintroduit le problème des collisions de noms.

Exemple 3 : Différence entre @use et @import

Comparons les deux approches pour bien comprendre la différence.

SCSS
// AVEC @import (ancienne méthode)
@import 'variables';
@import 'mixins';

.button {
  background: $primary; // Variable accessible directement
  @include rounded-corners; // Mixin accessible directement
}

// AVEC @use (nouvelle méthode)
@use 'variables';
@use 'mixins';

.button {
  background: variables.$primary; // Via namespace
  @include mixins.rounded-corners; // Via namespace
}

Avec @use, on sait exactement d'où vient chaque élément, ce qui rend le code plus explicite et moins sujet aux erreurs.

Exemples concrets et professionnels

Structure avancée avec @forward

Pour des projets professionnels, on utilise souvent @forward dans des fichiers index pour créer une API propre et organisée.

STRUCTURE
scss/
  abstracts/
    _colors.scss
    _spacing.scss
    _typography.scss
    _mixins.scss
    _index.scss          # Fichier index qui réexpose tout
  components/
    _buttons.scss
    _cards.scss
    _forms.scss
    _index.scss          # Fichier index pour les composants
  main.scss              # Point d'entrée principal

_colors.scss :

SCSS
// Variables de couleurs
$primary: #3b82f6;
$primary-light: #60a5fa;
$primary-dark: #2563eb;
$secondary: #8b5cf6;
$success: #10b981;
$warning: #f59e0b;
$danger: #ef4444;
$text: #1e293b;
$text-light: #64748b;
$background: #f8fafc;

_spacing.scss :

SCSS
// Variables d'espacement
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;
$spacing-xxl: 48px;

abstracts/_index.scss :

SCSS
// Réexposition des abstracts
@forward 'colors';
@forward 'spacing';
@forward 'typography';
@forward 'mixins' show rounded, shadow, flex-center; // Seulement certains mixins

main.scss :

SCSS
// Import des modules
@use 'abstracts' as a;
@use 'components' as c;

// Utilisation
body {
  background: a.$background;
  color: a.$text;
  font-family: 'Inter', sans-serif;
  padding: a.$spacing-md;
}

.button {
  @include c.button-base;
  background: a.$primary;
  color: white;
  padding: a.$spacing-sm a.$spacing-md;
  
  &:hover {
    background: a.$primary-dark;
  }
}

.card {
  @include c.card-base;
  border: 1px solid rgba(a.$primary, 0.1);
  padding: a.$spacing-lg;
  
  .card-title {
    color: a.$primary;
    margin-bottom: a.$spacing-md;
  }
}

Configuration de modules avec with

@use permet de configurer les variables d'un module à l'importation.

SCSS
// _config.scss
$primary: #3b82f6 !default;
$secondary: #8b5cf6 !default;
$theme: 'light' !default;

// main.scss
@use 'config' with (
  $primary: #7aa7ff,    // Surcharge de la valeur par défaut
  $theme: 'dark'        // Configuration du thème
);

.header {
  background: config.$primary; // Utilise #7aa7ff, pas #3b82f6
  
  @if config.$theme == 'dark' {
    color: white;
  } @else {
    color: #1e293b;
  }
}

La clause !default dans le module permet de définir des valeurs par défaut qui peuvent être surchargées avec with.

Migration progressive de @import vers @use

Pour les projets existants, voici une stratégie de migration :

  1. Étape 1 : Mettre à jour Sass à la version 1.23.0 ou supérieure.
  2. Étape 2 : Commencer par les nouveaux fichiers en utilisant @use.
  3. Étape 3 : Créer des fichiers index avec @forward pour les modules existants.
  4. Étape 4 : Remplacer progressivement les @import par des @use.
  5. Étape 5 : Utiliser sass-migrator (outil officiel) pour automatiser la migration.
Conseil terrain

Ne cherche pas à tout migrer d'un coup sur un gros projet. Commence par une petite partie non critique, teste bien, puis étends progressivement. La migration peut se faire sur plusieurs semaines ou mois selon la taille du projet.

Bonnes pratiques

Règles d'or pour @use et @forward

  • Utiliser @use par défaut pour tous les nouveaux projets.
  • Réserver @forward aux fichiers index qui organisent les exports.
  • Nommer clairement les namespaces : des noms courts mais explicites.
  • Limiter l'exposition : utiliser show et hide avec @forward pour contrôler l'API.
  • Utiliser !default pour les variables configurables.
  • Éviter as * sauf pour les utilitaires très génériques.
  • Documenter l'API : commenter ce qui est exposé et comment l'utiliser.
  • Rester cohérent : une fois une convention choisie, l'appliquer partout.
À retenir

@use + @forward = SCSS modulaire, lisible, maintenable et scalable. Cette approche moderne résout les problèmes historiques de @import et prépare ton code pour l'avenir.

Conventions de nommage pour les modules

EXEMPLES
// Bonnes pratiques
@use 'abstracts/variables' as vars;
@use 'components/buttons' as btn;
@use 'layout/header' as header;
@use 'utilities' as utils;

// Noms de namespace courts mais clairs
@use 'settings/colors' as c;        // OK si clair dans le contexte
@use 'settings/typography' as typo; // OK si clair

// À éviter
@use 'abstracts/variables' as v;    // Trop court
@use 'components/buttons' as b;     // Trop court
@use 'layout/header' as h;          // Trop court

Erreurs courantes

Erreur 1 : Mélanger @import et @use

Cela fonctionne parfois, mais crée des comportements imprévisibles et difficiles à déboguer. @import et @use ont des règles de portée différentes.

Attention

Évite absolument de mélanger les deux dans un même projet. Si tu dois migrer, fais-le progressivement mais de manière cohérente.

Erreur 2 : Tout exposer avec @forward

Réexposer toutes les variables et mixins sans filtrage crée une API trop large et difficile à maintenir. Les utilisateurs ne savent pas ce qu'ils peuvent utiliser en toute sécurité.

SCSS
// MAUVAIS - Tout est exposé
@forward 'colors';
@forward 'spacing';
@forward 'typography';
@forward 'mixins';
@forward 'functions';

// BON - API contrôlée
@forward 'colors';
@forward 'spacing';
@forward 'typography';
@forward 'mixins' show rounded, shadow, flex-center;
@forward 'functions' show rem, em, color-lighten;

Erreur 3 : Oublier les namespaces

Après des années avec @import, on a l'habitude d'accéder directement aux variables. Avec @use, il faut penser au namespace.

SCSS
// ERREUR - Variable non trouvée
@use 'variables';

.button {
  background: $primary; // ERREUR : $primary n'existe pas ici
}

// CORRECT - Avec namespace
@use 'variables';

.button {
  background: variables.$primary; // CORRECT
}

Erreur 4 : Importer plusieurs fois le même module

Avec @import, on pouvait importer plusieurs fois le même fichier. Avec @use, chaque module est chargé une seule fois par fichier, mais il faut faire attention aux imports circulaires.

SCSS
// _a.scss
@use 'b';
$value: 'a';

// _b.scss  
@use 'a'; // ERREUR : import circulaire
$value: 'b';

// main.scss
@use 'a'; // Provoque une erreur

Sass détecte les imports circulaires et affiche une erreur claire.

Résumé du chapitre

Ce que vous avez appris
@use remplace @import pour une gestion modulaire et sécurisée des imports SCSS.
Chaque module importé avec @use a son propre namespace qui évite les collisions de noms.
@forward permet de créer des APIs propres en réexposant sélectivement des éléments.
La clause with permet de configurer les variables d'un module à l'importation.
Cette approche moderne rend le code plus robuste, maintenable et professionnel.

Prochain chapitre : Mixins SCSS

Maintenant que nous savons organiser et structurer notre code SCSS de manière moderne, passons à un outil puissant pour éviter la duplication : les mixins. Dans le prochain chapitre, nous découvrirons comment créer des blocs de styles réutilisables, avec ou sans paramètres, pour rationaliser notre code et gagner en productivité.

  • Comprendre ce qu'est un mixin et pourquoi l'utiliser
  • Créer des mixins simples et paramétrés
  • Utiliser les mixins pour les styles répétitifs
  • Créer des mixins pour la responsivité
  • Bonnes pratiques et pièges à éviter avec les mixins