28 janvier 2025

Comment migrer une architecture SCSS vers la règle « @use »

J’utilise depuis de nombreuses années maintenant la méthodologie ITCSS pour organiser mes styles dans mes projets. Elle a fait ses preuves dans tous mes projets et notamment l’architecture frontend que j’ai créé pour Specify il y a 6 ans.

ITCSS en quelques mots

ITCSS pour « Inverted Triangle CSS » est une méthodologie d’architecture qui nous aide à structurer nos feuilles de style en bénéficiant de la cascade au maximum tout en contrôlant la spécificité de nos règles CSS à grande échelle.

L’idée principale est de structurer notre CSS en plusieurs niveaux qui peuvent être représentés selon un triangle inversé :

Représentation de mon architecture SCSS inspirée de ITCSS et simplifiée en 3 différents niveaux : utils, base et components.

Voici en pratique à quoi ressemble mon architecture CSS inspirée de ITCSS :

Représentation de mon architecture Sass actuelle. Mes fichiers SCSS sont organisés en 3 niveaux :
1. Utils
2. Base
3. Fonts

J’utilise seulement 3 niveaux :

  1. Utils : contient tous mes design tokens créés en variables CSS natives et mixins, toutes mes variables de style générales et mes classes utilitaires
  2. Base : la base du CSS de mon front. Donc mes styles de base ciblant des balises et mon CSS reset (ici _sanitize.scss)
  3. Fonts : mes imports de fonts que j’aurais pu aussi directement mettre dans le niveau « Utils »

Vous remarquerez que je n’ai pas de fichiers SCSS listés pour le niveau « Components ». C’est normal puisque tous mes composants respectent la structure suivante et ont leur propre fichier SCSS :

📁 MyComponent
  ├── MyComponent.vue
  ├── MyComponent.scss
  └── MyComponent.story.ts

Mon architecture actuelle

Mon architecture SCSS est plutôt simple : des fichiers SCSS d’un même niveau sont dans le même dossier. Et parfois, des fichiers sont organisés par dossier.

Voici un exemple avec mes fichiers mixins créés dans un dossier mixins/ tous importés depuis le même fichier _mixins.scss :

📁 01-utils
    └── 📁 variables
    |   ├── _mixins.scss
    |   ├── _text-styles.scss
    └── _mixins.scss <-- 🛢️ barrel file

Ce fichier _mixins.scss importe tous les fichiers contenant nos mixins :

// ----------------------
// == Mixins
// ----------------------
@import 'mixins/mixins';
@import 'mixins/text-styles';

Ce fichier est par la suite lui même importé dans mon fichier style.scss :

Également, j’ai parfois besoin d’utiliser des mixins dans les fichiers SCSS de mes composants. Comme le monde est bien fait, Vite me permet d’automatiser l’import de code SCSS en ajoutant du « code additionnel » :

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
            @import './src/assets/styles/01-utils/mixins';
        `,
      },
    },
  },
})

Jusqu’à maintenant tout allait bien jusqu’à ce que je tombe sur cette erreur dans mon terminal récemment :

Deprecation Warning: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.

Il était temps d’importer mes fichiers SCSS d’une manière plus récente et pérenne.

Migrer nos imports de « @import » vers « @use »

Sass fourni un outil en ligne de commande pour nous aider à migrer nos imports vers la règle @use.

Il fait le job mais pas entièrement puisque renommer tous nos @import en @use n’était pas suffisant dans mon cas.

Chaîner les @use comme je le faisais pour les @import ne fonctionne que si vos fichiers ne contiennent pas de membres Sass (variables, mixins, functions).

Mais moi j’ai justement des mixins à importer dans mon style.scss et dans les fichiers SCSS de tous mes composants.

En fouinant un peu j’ai trouvé la règle @forward qui comme son nom l’indique permet de transférer des functions, variables et mixins vers un fichier parent.

Voici donc le nouveau contenu de notre barrel file _mixins.scss :

// ----------------------
// == Mixins
// ----------------------
@forward 'mixins/mixins';
@forward 'mixins/text-styles';

Et celui de notre fichier parent style.scss :

// 01 - Utils
// ---------------------
@use '01-utils/variables';
@use '01-utils/lint';
@use '01-utils/mixins' as *;
@use '01-utils/site-settings';
@use '01-utils/utility-classes';
// 02 - Base
// ---------------------
@use '02-base/sanitize';
@use '02-base/base';
// 03 - Fonts
// ---------------------
@use '03-fonts/fonts';

Le as * me permet de ne pas définir de namespace pour mon barrel file _mixins.scss. Je peux donc continuer à utiliser mes mixins par leur nom sans avoir à les préfixer par le namespace créé par défaut par la règle @use.

// Sans 'as *' (@use '01-utils/mixins';)
@include mixin.my-mixin;
// Avec 'as *' (@use '01-utils/mixins' as *;)
@include my-mixin;

Bien entendu il faut aussi penser à modifier l’import de notre fichier mixins.scss dans notre configuration Vite :

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @use './src/assets/styles/01-utils/mixins' as *;
        `,
      },
    },
  },
})

En résumé

Si vous devez migrer une architecture SCSS de la règle @import vers @use vous devez respecter la règle suivante : si vous avez des fichiers SCSS intermédiaires qui relaient des fichiers enfants ne contenant que du CSS alors vous pouvez chainer les @use. Sinon vous devez utiliser la règle @forward sur vos barrel files.

3 mai 2024

Designops meetups: une exploration des Design Tokens

Les Design Tokens représentent une révolution dans le domaine du design numérique, offrant des solutions innovantes pour la standardisation, la...
Designops meetups: une exploration des Design Tokens
28 février 2024

Atelier Typescript Avancé

Développez vos compétences techniques avec notre Atelier Typescript Avancé ! Dans vos pratiques de développement, en tant que lead d’une...
Atelier Typescript Avancé
24 janvier 2024
CSS

CSS logical properties : la révolution pour l’internationalisation

Les logical properties sont une famille de propriétés CSS permettant de s’affranchir d’une sémantique physique au profit d’une sémantique logique....
CSS logical properties : la révolution pour l’internationalisation