Archives Wild Code School
Symfony

04.1 - Symfony : gestion des assets avec AssetMapper

Quête 6 sur 35

Objectifs

  • ✅ Découvrir le nouveau gestionnaire d'assets de Symfony
  • ✅ Installer des dépendances
  • ✅ Organiser tes fichiers CSS ou SCSS
  • ✅ Gérer les images de ton webdesign
title
Introduction

Intégré depuis la version 6.3, AssetMapper est le bundle officiel pour gérer les assets dans Symfony. Le concept est né du constat que dorénavant tous les navigateurs Internet acceptaient l'exécution de code JavaScript moderne. Cette quête revient sur ce « JavaScript moderne » et présente en préambule ce que sont les modules en JavaScript pour pouvoir mieux comprendre comment fonctionne AssetMapper. Tu verras ensuite comment gérer les fichiers CSS, JS, et tout type d'asset, mais également les dépendances frontend et comment travailler avec des fichiers SCSS dans une application Symfony.

Cette quête est assez longue en terme de contenus car nous avons souhaité aborder un maximum d'explications. Mais tu vas voir qu'au final il n'y a pas grand chose à faire 😉.

Sommaire

Un peu d'histoire : ECMAScript 6

Lorsque l'on parle de JavaScript moderne en introduction de cette quête, on entend les fonctionnalités disponibles depuis la deuxième mise à jour majeure du langage, sous le nom ECMAScript 6 (ES6) publiée en 2015. La version ES6 de JavaScript ne date donc pas d'hier, mais son implémentation native dans les principaux navigateurs Internet a mis un peu de temps. Il était recommandé aux développeurs web il n'y a encore pas si longtemps, d'avoir recours à un bundler tel que Webpack, le plus connu, pour être certain de produire un code compatible avec tous les navigateurs.

La liste des fonctionnalités qui avait été publiée lors de cette mise à jour est assez longue. N'hésite pas à consulter la ressource ci-dessous pour en connaître le contenu.

↗
ECMAScript 6 (ES6)

Également connue sous le nom ECMAScript 2015

w3schools.com

Voici quels en étaient les points forts dont tu as sûrement déjà entendu parlé :

Mais surtout une fonctionnalité très importante sur laquelle repose AssetMapper : les Modules

Les modules ES6

↗
JavaScript modules
w3schools.com

Les modules JavaScript nous permettent d'organiser notre code JavaScript en fichiers séparés grâce à un système d'import et d'export.

  1. 1

    Version classique

    Prenons l'exemple d'un fichier greet.js dans lequel serait déclarée une fonction sayHello().

    js
    //greet.js
    const sayHello = (name) => {
        return 'Hello ' + name;
    };
    

    Jusqu'ici tu as appris à intégrer du code JavaScript grâce à la balise <script> et son attribut src. Pour appeler cette fonction dans une page HTML, tu aurais naturellement écrit ce qui suit pour disposer immédiatement de la fonction sayHello() :

    html
    <!--index.html-->
    <script src="./greet.js"></script>
    <script>
       console.log(sayHello("John"));
    </script>
    
  2. 2

    Import/export d'un module

    Grâce au système d'import et d'export des modules JavaScript, on obtient exactement le même résultat. Voici ce que cela donne.

    html
    <script type="module">
      import sayHello from "./greet.js";
      console.log(sayHello("John"));
    </script>
    
    js
    const sayHello = (name) => {
      return 'Hello ' + name;
    };
    
    export default sayHello;
    

    Si on pousse un peu plus loin la réflexion, on peut tout à fait imaginer la structure suivante où l'on importe un module qui importe un autre module :

    html
    <script type="module">
      import "./app.js";
    </script>
    
    js
    import sayHello from "./greet.js";
      
    console.log(sayHello("John"));
    
    js
    const sayHello = (name) => {
      return 'Hello ' + name;
    };
    
    export default sayHello;
    

    Dans cet exemple, on dit que le fichier app.js joue le rôle de point d'entrée. Il ne contient qu'un minimum de code et principalement des imports d'autres fichiers qui, eux, contiennent la logique métier. (💡 Retiens bien cette notion de point d'entrée, nous en reparlerons un peu plus tard). Et il n'y aurait pas de limites à ces imports en cascade. Un peu comme ce que tu as appris à faire en PHP grâce aux namespace et aux use.

    Et de la même manière qu'en PHP, la caractéristique de ce système d'import/export des modules est que les variables (et donc les fonctions ou les classes) restent isolées dans le scope des fichiers. Ils doivent absolument être exportées et importées pour être utilisables ailleurs.

    Reprenons notre exemple et ajoutons une fonction sayGoodbye() au fichier greet.js comme ceci :

    html
    <script type="module">
      import "./app.js";
    </script>
    
    js
    import sayHello from "./greet.js";
      
    console.log(sayHello("John"));
    console.log(sayGoodbye("John"));
    
    js
    const sayHello = (name) => {
      return 'Hello ' + name;
    };
    
    const sayGoodbye = (name) => {
      return 'Goodbye ' + name;
    }
    
    export default sayHello;
    

    La fonction sayGoodbye("John") invoquée dans le fichier app.js génère une erreur. Elle n'a pas été exportée ni importée et appartient pour le moment uniquement au scope du fichier greet.js.

    sh
    Hello John
    ❌ Uncaught ReferenceError: sayGoodbye is not defined
    

    De cette manière, les fichiers peuvent coexister en toute sécurité.

    Nous allons voir qu'en exploitant cette fonctionnalité, AssetMapper va nous donner la possibilité de structurer notre code JavaScript qui sera composé de fonctions ou de classes réutilisables et isolées les unes des autres. Et tout ceci nativement dans les navigateurs, sans utiliser de bundler 🥳.

    La courte vidéo ci-dessous explique tout ceci pas à pas avec une classe en exemple. ☝️ MUST WATCH 👇

    ↗
    https://symfonycasts.com/screencast/asset-mapper/es6-browser#play

    Doing Modern JS Right in your Browser Explication en vidéo (7 minutes) de Ryan Weaver - contributeur majeur de Symfony et SymfonyCast.

    symfonycasts.com

AssetMapper ready

Si tu as installé une version 6.3 de Symfony ou supérieure, ce qui est probablement le cas, tu n'as rien à faire, AssetMapper est déjà installé et préconfiguré. Mais pour information, si tu dois l'installer sur un projet, voici la commande à lancer avec composer.

bash
composer require symfony/asset-mapper symfony/asset symfony/twig-pack

Comme pour d'autres bundles, SymfonyFlex exécute quelques recettes après le téléchargement des dépendances. Pour AssetMapper, cela concerne les fichiers ci-après. Ouvre-les avec ton IDE et regardons de quoi il s'agit.

  1. 1

    config/packages/asset_mapper.yaml

    Un fichier de configuration YAML où est défini le chemin vers le dossier de tes assets.

  2. 2

    importmap.php

    À la racine de ton projet, ce fichier sera automatiquement mis à jour à l'installation de chaque nouvelle dépendance. C'est également ici que tu pourras définir les points d'entrée de ton application. 💡 point d'entrée : nous y voilà 😎

    php
    //importmap.php
    return [
        'app' => [
            'path' => './assets/app.js',
            'entrypoint' => true,
        ],
    

    Oui il s'agit bien d'un tableau PHP et son rôle est de permettre à AssetMapper de générer les balises HTML <link> et <script>. Et si tu regardes le fichier base.html.twig, tu remarques que SymfonyFlex a également écrit ceci : {{ importmap('app') }}. C'est ce helper Twig qui fera le lien.

  3. 3

    assets/app.js

    Le fichier JavaScript principal, ce fameux point d'entrée, dans lequel tu pourras importer d'autres fichiers. Il contient d'ailleurs déjà deux imports.

    js
    import './bootstrap.js';
    import './styles/app.css';
    
    • Le premier ./bootstrap.js : ⚠️ il ne s'agit pas du framework frontend du même nom que tu connais sans doute déjà. Il s'agit d'un fichier lié à la bibliothèque Stimulus dont nous parlerons dans une prochaine quête. Ne supprime pas cette ligne mais n'y prête pas attention pour le moment.
    • Le second ./styles/app.css : une référence au fichier app.css généré lui aussi par SymfonyFlex au moment de l'installation et dont tu peux te servir pour définir tes règles de style. C'est d'ailleurs grâce à ce fichier que tu as une page sur fond bleu 😎.
    Info

    À noter : l'import de fichiers CSS dans un fichier JavaScript est d'ordinaire impossible. Si tu essaies de le faire dans contexte classique, tu obtiendras l'erreur suivante dans la console de ton navigateur :

    ❌ Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/css". Strict MIME type checking is enforced for module scripts per HTML spec.

    Cela fonctionnerait indirectement avec un bundler comme Webpack ou Vite car il injecterait un lien vers la feuille de style dans la page HTML. Ici c'est AssetMapper qui se charge d'ajouter ce lien vers le fichier app.css au DOM. D'ailleurs, si tu inspectes le code source de ta page d'accueil, tu trouveras cette ligne dans la partie <head> (les xxxxx étant remplacés par une série de chiffres et de lettres) :

    html
    <link rel="stylesheet" href="/assets/styles/app-xxxxxxxxx.css">
    

    Consulte cette autre vidéo de Ryan Weaver à 1:16:06 si tu veux comprendre comment cela marche.

Les images de décoration

Pour faire référence à tes images de décoration (pas les images de contenu qui, elles, seront gérées autrement), tu vas pouvoir utiliser le helper Twig asset(). Voici par exemple comment afficher l'image duck.png qui serait située dans le dossier assets/images.

html
<img src="{{ asset('images/duck.png') }}" alt="" />

Plus d'infos concernant les chemins vers des fichiers au sein d'un CSS : Paths Inside of CSS Files

À noter : il faut indiquer le chemin complet vers le fichier en question DEPUIS le dossier assets.

Premières conclusions

Et voilà, tu sais à peu près tout d'AssetMapper ! Un fichier importmap.php qui liste les points d'entrée de ton application qui, eux, importent tes fichiers JavaScript et CSS. Et ce fichier importmap.php se charge de générer les balises HTML <link> et <script> ainsi que les fichiers finaux dont les noms seront versionnés (app-xxxxxxxxx.css, app-xxxxxxxxx.js, etc.). La ressource suivante te donne un exemple d'utilisation.

↗
Importmaps & Writing JavaScript

Écrire du JavaScript avec AssetMapper.

symfony.com

Mais alors, il n'y a rien à faire de plus ? Laisse-moi réfléchir 🤔.

Non 😀, c'est parti tu peux coder 🚀.

Ah si, nous allons parler du cas où tu souhaites installer d'autres dépendances. Mais d'abord, révisons un peu tout ça.

🎯 Quiz

quiz
false|||false|||true
# AssetMapper repose sur les modules ES6
[] Et génère l'appel vers le fichier principal **app.js** avec le code HTML : 
```html
<script src="app.js"></script>
```
[x] Et génère l'import du point d'entrée **app.js** avec le code HTML :
```html
<script type="module">import 'app';</script>
```
# En utilisant AssetMapper, quelle écriture me permet d'importer la fonction hello() du fichier myAwesomeScript.js dans mon fichier app.js ?
[] 
```js
const myAwesomeScript = require('myAwesomeScript.js');
myAwesomeScript.hello();
```
[x] 
```js
import hello from 'myAwesomeScript.js';
```
[] 
```css
@import 'myAwesomeScript.js';
hello();
```

# AssetMapper ajoute une série de chiffres et de lettres aux noms des fichiers app.js et app.css à chaque fois qu'ils sont modifiés pour générer des noms uniques.
[x] En procédant ansi, les navigateurs forceront le téléchargement des nouvelles versions au lieu d'utiliser les versions mises en cache. On dit alors que les noms sont versionnés.
[] Cela permet de renforcer la sécurité en brouillant les noms des fichiers.
[] Cette contrainte est dictée par Git.

Installer des dépendances

Tu as sans doute remarqué un autre dossier dans le dossier assets. Le dossier vendor. Étrange 🤔. Que fait donc ce dossier ici ? Je te rassure, il ne s'agit pas d'une erreur de manipulation. Ce dossier est bien à sa place, et comme celui du même nom en racine, il n'est pas versionné avec Git. Tu le devines sans doute, ce dossier va héberger tes dépendances frontend.

  1. 1

    De Webpack Encore à AssetMapper

    Avant l'arrivée d'AssetMapper, Symfony préconisait l'utilisation de Node et du gestionnaire Yarn pour gérer les dépendances. Le builder Webpack était alors configuré (sous le bundle Webpack Encore) pour manipuler, compiler, transpiler, minifier… nos assets et rendre nos fichiers JavaScript compatibles avec tous les navigateurs. Toutes les dépendances frontend d'un projet étaient alors stockées dans un dossier node_modules.

    Mais ça c'était avant !

    Aujourd'hui AssetMapper propose de se connecter à NPMJS pour télécharger toutes les dépendances dont tu as besoin dans le fameux dossier vendor du dossier assets. Et cela va pouvoir se faire grâce à Symfony CLI et la commande :

    bash
    php bin/console importmap:require nom_du_package
    
    Info

    Pour trouver le nom exact d'un package, rends-toi sur NPMJS et recherche la dépendance qui t'intéresse. Lorsque tu suis le lien, tu obtiens le nom en début de page ou via la commande npm i qui est proposée. Voici quelques exemples :

    • Pour Pico CSS c'est @picocss/pico
    • Bootstrap : bootstrap
    • Uikit : uikit
    • etc.
  2. 2

    Installer Bootstrap

    Entrons dans le vif du sujet et installons Bootstrap, le célèbre framework frontend cette fois-ci.

    Lance la commande suivante :

    bash
    php bin/console importmap:require bootstrap
    

    Le téléchargement est très rapide et lorsqu'il est terminé, la console t'indique que trois entrées ont été ajoutées au tableau du fichier importmap.php.

    php
    return [
        //...
        'bootstrap' => [
            'version' => '5.3.3',
        ],
        '@popperjs/core' => [
            'version' => '2.11.8',
        ],
        'bootstrap/dist/css/bootstrap.min.css' => [
            'version' => '5.3.3',
            'type' => 'css',
        ],
    ];
    

    Nous n'en avons pas parlé tout à l'heure, mais côté HTML une des balises <script> qui est générée possède l'attribut type="importmap". Regardons son contenu.

    html
    <script type="importmap" data-turbo-track="reload">
    {
        "imports": {
            "app": "/assets/app-dc80e6c89135215834fae357c55df6c3.js",
            "/assets/bootstrap.js": "/assets/bootstrap-c423b8bbc1f9cae218c105ca8ca9f767.js",
            "/assets/styles/app.css": "data:application/javascript,",
            "@symfony/stimulus-bundle": "/assets/@symfony/stimulus-bundle/loader-e1ee9ace0562f2e6a52301e4ccc8627d.js",
            "@hotwired/stimulus": "/assets/vendor/@hotwired/stimulus/stimulus.index-b5b1d00e42695b8959b4a1e94e3bc92a.js",
            "/assets/@symfony/stimulus-bundle/controllers.js": "/assets/@symfony/stimulus-bundle/controllers-9d42643c079ab11f27a3a9614f81cc2f.js",
            "/assets/@symfony/ux-turbo/turbo_controller.js": "/assets/@symfony/ux-turbo/turbo_controller-ce5e32dafdec0b7752f02e3e2cb25751.js",
            "/assets/controllers/hello_controller.js": "/assets/controllers/hello_controller-55882fcad241d2bea50276ea485583bc.js",
            "@hotwired/turbo": "/assets/vendor/@hotwired/turbo/turbo.index-810f44ef1a202a441e4866b7a4c72d11.js",
            "bootstrap": "/assets/vendor/bootstrap/bootstrap.index-c0423c99f6075e6b1cef7579b5c00d32.js",
            "@popperjs/core": "/assets/vendor/@popperjs/core/core.index-ceb5b6c0f9e1d3f6c78ef733facfdcda.js",
            "bootstrap/dist/css/bootstrap.min.css": "data:application/javascript,document.head.appendChild%28Object.assign%28document.createElement%28%22link%22%29%2C%7Brel%3A%22stylesheet%22%2Chref%3A%22%2Fassets%2Fvendor%2Fbootstrap%2Fdist%2Fcss%2Fbootstrap.min-1712f0378f8675ca7cd423d6262fcccf.css%22%7D%29%29"
        }
    }
    </script>
    

    Tu y retrouves à peu près tous les index du tableau importmap.php dont ton point d'entrée app.js mais également ta dépendance Bootstrap fraîchement installée. Ce qu'il faut comprendre ici c'est que tu vas pouvoir te servir des index du tableau, et notamment bootstrap et bootstrap/dist/css/bootstrap.min.css pour y faire référence dans tes fichiers JavaScript et pouvoir ainsi charger les fichiers associés. Il seront automatiquement « mappés » par le navigateur.

    Ouvre ton fichier assets/app.js et ajoutes-y les lignes suivantes :

    js
    import 'bootstrap/dist/css/bootstrap.min.css';
    import 'bootstrap';
    

    À présent rends-toi sur la documentation de Bootstrap, récupère le code d'un composant et intègre-le à ta page. Tu devrais voir apparaître ton composant fonctionnel.

  3. 3

    Exemple avec une Navbar

    Voici ce que tu pourrais mettre en place pour afficher une Navbar Bootstrap (avec dropdown et menu burger responsive)

    js
    import './bootstrap.js';
    /*
     * Welcome to your app's main JavaScript file!
     *
     * This file will be included onto the page via the importmap() Twig function,
     * which should already be in your base.html.twig.
     */
    import './styles/app.css';
    
    import 'bootstrap/dist/css/bootstrap.min.css';
    import 'bootstrap';
    
    
    html
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                Dropdown
              </a>
              <ul class="dropdown-menu">
                <li><a class="dropdown-item" href="#">Action</a></li>
                <li><a class="dropdown-item" href="#">Another action</a></li>
                <li><hr class="dropdown-divider"></li>
                <li><a class="dropdown-item" href="#">Something else here</a></li>
              </ul>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled" aria-disabled="true">Disabled</a>
            </li>
          </ul>
          <form class="d-flex" role="search">
            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
            <button class="btn btn-outline-success" type="submit">Search</button>
          </form>
        </div>
      </div>
    </nav>
    
    twig
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>{% block title %}Welcome!{% endblock %}</title>
            {% block stylesheets %}
            {% endblock %}
    
            {% block javascripts %}
                {% block importmap %}{{ importmap('app') }}{% endblock %}
            {% endblock %}
        </head>
        <body>
            {% include '_navbar.html.twig' %}
            {% block body %}{% endblock %}
        </body>
    </html>
    

    Plutôt simple non ?

  4. 4

    Désinstaller une dépendance

    Tu as vu que la bibliothèque @popperjs/core dont dépend Bootstrap avait été automatiquement téléchargée par AssetMapper. Cette fonctionnalité du bundle est très pratique pour être sûr de ne rien oublier. En revanche pour désinstaller une dépendance, il te faudra lister l'ensemble des entrées ajoutées en utilisant la commande php bin/console importmap:remove nom_du_package1 package2 etc.. Voici par exemple la commande pour désinstaller bootstrap.

    bash
    php bin/console importmap:remove bootstrap @popperjs/core bootstrap/dist/css/bootstrap.min.css
    

    Travailler avec des fichiers SCSS

    Petit rappel sur ce qu'est le SCSS avec la quête suivante.

    Quêtes liées

    Travailler avec des fichiers Sass (scss) était une fonctionnalité très utilisée dans un contexte de builder comme Webpack. Cela reste possible avec AssetMapper grâce au sass-bundle de SymfonyCasts.

    Pour l'installer, comme d'habitude avec composer, lance la commande suivante :

    bash
    composer require symfonycasts/sass-bundle
    

    Renomme ensuite ton fichier assets/app.css en => app.scss. Pense également à mettre à jour le fichier app.js

    js
    import './styles/app.scss';
    

    Lorsque tu recharges ta page, tu as cette erreur :

    Important

    An exception has been thrown during the rendering of a template […]/var/sass/app.output.css doesn't exist

    Eh oui, il faut lancer la commande de build pour demander au bundle sass-bundle de convertir tes fichiers Sass en fichier CSS :

    bash
    php bin/console sass:build --watch
    

    Lorsque tu recharges ton navigateur, tout fonctionne correctement et si tu effectues des modifications de style, ils sont bien pris en compte.

    Attention

    Très important si tu utilises sass-bundle pour faire du SCSS Pour être sûr de ne pas oublier de lancer la commande de build à chaque fois que tu démarres ton projet, tu peux ajouter un fichier .symfony.local.yaml en racine de ton dossier avec ce qui suit à l'intérieur. Cela aura pour effet de démarrer automatiquement le build à chaque symfony server:start et chaque fois que tu modifies tes fichiers.

    yaml
    workers:
      # ...
      sass:
        cmd: ['symfony', 'console', 'sass:build', '--watch']
    

    Plus d'info ici https://symfony.com/bundles/SassBundle/current/index.html#symfony-cli

    Si tu utilises du SCSS c'est probablement pour travailler avec les fichiers d'origine d'un framework.

    Reprenons l'exemple de Bootstrap que tu as installé tout à l'heure. Si tu te souviens bien, tu faisais appel au fichier CSS minifié bootstrap.min.css téléchargée depuis NPMJS. Cette feuille de style ne te permet pas de changer le thème facilement. Pour cela, tu vas récupérer les fichiers SCSS du framework ce qui te permettra de changer toutes les variables selon ton design. Cette fois-ci, c'est composer qui va être utilisé et qui va télécharger les fichiers source depuis Packagist.

    Lance cette commande :

    bash
    composer require twbs/bootstrap
    

    Tu peux maintenant y faire référence et l'importer dans ton fichier app.scss comme ceci :

    scss
    @import '../../vendor/twbs/bootstrap/scss/bootstrap';
    

    Enfin, retire l'appel au fichier minifié bootstrap.min.css depuis le point d'entrée app.js puisqu'il ne sert plus à rien.

    Retrouve toute la marche à suivre sur la documentation du bundle Sass-bundle.

    Pour changer la couleur primary, tu peux par exemple procéder comme ceci :

    scss
    //app.scss
    $primary: #8302ab;
    @import '../../vendor/twbs/bootstrap/scss/bootstrap';
    

    Retrouve les recommandations complètes à la page Sass de la documentation de Bootstrap.

    Info

    Si tu souhaites installer un autre framework que Bootstrap et utiliser les fichiers source SCSS, il te faudra aussi les télécharger depuis Packagist avec le nom exact du package. Utilise la barre de recherche comme tu l'as fait sur NPMJS. Voici quelques exemples :

    • Pour Pico CSS c'est composer require picocss/pico
    • Bootstrap : composer require twbs/bootstrap
    • Uikit : composer require uikit/uikit
    • etc.

    Consulte ensuite les documentations respectives pour importer les fichiers dans ton fichier d'entrée app.scss.

En résumé

Pour gérer les assets d'un projet web avec AssetMapper dans Symfony :

  1. Utiliser le point d'entrée app.js pour importer tes autres fichiers JavaScript en mode ES6 modules ainsi que tes dépendances.
  2. Utiliser le fichier app.css qui sera également importé dans le point d'entrée.
  3. Si tu souhaites utiliser des dépendances frontend, lancer la commande :
    bash
    php bin/console importmap:require nom_de_la_dépendance
    
    Il faudra ensuite récupérer via le tableau du fichier importmap.php le nom de l'index à importer dans ton fichier JavaScript app.js.
  4. Si tu souhaites travailler avec du SCSS, il faudra installer le bundle sass-bundle de SymfonyCasts et lancer la commande php bin/console sass:build --watch à chaque fois que tu démarres ton projet. Il faudra également télécharger les fichiers source SCSS depuis Packagist avec Composer et la commande composer require vendor_name/package_name puis les importer dans ton fichier SCSS.

Mise en production

Une dernière chose qui ne te concerne pas tout de suite mais que tu dois savoir en tant que développeur. Tout ce que tu as vu dans cette quête est valable en mode développement. Si tu mets ton projet en ligne, tu passeras en mode production. Il faudra alors lancer la commande suivante pour copier tout le contenu du dossier assets dans le dossier public :

bash
php bin/console asset-map:compile

Serving assets in DEV vs PROD