Développement Front End Moderne Avec Symfony 4

Si vous voulez faire un site responsive design, je vous recommande d’utiliser Bootstrap. Seulement voilà, dans un développement d’application web moderne, il ne suffit pas de télécharger les fichiers CSS et JS de Bootstrap, il faut le faire avec l’outil de développement de Symfony 4, pour profiter de beaucoup des configurations et manipulations déjà faites.

Le développement Front End en 2019

Bien avant déjà lorsque j’ai commencé à développer avec AngularJS (version 1) en 2015, on utilisait un process de build spécifique au Front End, ainsi avec NodeJs, NPM, Gulp ou Grunt, on compilait les fichier LESS ou SCSS en CSS, on minifiait les fichiers Javascript pour qu’ils prennent moins de place, et on bundlait en un seul fichier les fichiers JS, afin de n’avoir qu’un seul fichier à téléchargeait pour accélérer les téléchargements (le protocola HTTP 1.1 ne téléchargeait simultanément environ que 7 fichiers en même temps).

Donc pour Symfony, jusqu’ici on ne faisait que du Back End, du PHP, maintenant il nous faut un process de build et de bundling pour compiler les fichiers Sass (SCSS) et minifier les fichiers Javascript.

Mise en place du process Front End avec Symfony 4

Installez Yarn

Symfony possède un composant pour le Front End, Encore, pour vous aider dans cette tâche, suivez les instructions. Nous allons encore utiliser une dernière fois Composer pour installer le bundle Encore, puis nous allons passer directement aux outils Front End comme Yarn à installer depuis le dépôt officiel.

composer require symfony/webpack-encore-bundle
yarn install

Sous Symfony Flex, les deux commandes ci-dessus vont créer un répertoire assets/, le fichier webpack.config.js, ajouter le répertoire node_modules à ignorer pour Git.

Process Front End, Javascript moderne, modules

Maintenant comme nous ne travaillons qu’avec des fichiers Javascript et CSS, vous entendrez beaucoup parler de NodeJS (le programme responsable de faire tourner tous les programmes et utilitaires pour tout ce qui a trait au Javascript), NPM (Node Package Manager, le programme qui a besoin de NodeJs pour tourner, et qui est responsable de télécharges les librairies Javascript pour le développement Front End, comme Webpack, Yarn, Jquery, Angular, VueJS, ReactJS, BabelJS, Gulp etc).

Symfony 4 a choisi de travailler avec Webpack pour la partie Js et CSS de votre application Web. Webpack est un bundler de modules Javascript. Qu’est ce qu’un module? disons que pour travailler de façon moderne en Frant End Javascript, il faut organiser votre code en module, cela n’a rien à voir avec les classes Javascript.

Un module est une organisation thématique de votre code Javascript, par exemple, vous pouvez regrouper dans un module des fonctions mathématique pour calculer les aires de figures géométriques. Le but étant de donner un nom a votre module, afin de pouvoir l’utiliser dans d’autres modules.

Si vous choisissez de travailler avec les modules Javascript il faut que tout votre application soit sous forme de modules, il n’est pas du tout recommandé de travailler avec un mix de module et de fichier Javascript à inclure.

Organiser votre programme en modules nécessite un apprentissage certains, car il y a beaucoup de nouvelles notions, et il est largement moins intuitif que de travailler de manière classique* et requiert plus de travail.

Non seulement il vous faudra vous familiariser aves les modules, mais aussi avec les outils de build. Normalement ce n’est pas nécessaire, mais les outils augmentent votre productivité au prix de temps passé à vous documenter sur comment les faire marcher, les quelques lignes ci-dessous vous guideront je l’espère.

Configuration de l’outil Encore fourni par Symfony

Node-sass pour compiler le Sass en CSS, Sass-loader pour charger le Sass en mémoire

Cet outil est prévu pour compiler les Sass en CSS, à condition d’installer deux autre package node-sass et sass-loader (ce dernier va charger en mémoire les SCSS et rien d’autre)

yarn add sass-loader@^7.0.1 node-sass --dev

L’opération va vous installer une cinquantaine de dépendances directe ! (au passage NPM est un peu monstrueux en terme de taille, le répertoire node_modules sous Windows peut présenter quelques difficultés si vous l’effacez directement.)

Compiler les fichiers avec Webpack

Maintenant que nous avons installé le nécessaire, il est temps de compiler les fichiers Sass et bundler les fichiers Javascript ! Webpack est un programme qui tourne sous NodeJS, qui va principalement combiner tous les fichiers Javascripts pourvu qu’ils aient été écrits sous forme de modules, et combiner en un seul fichier. De même les fichiers Sass seront compilé en CSS et sauvé dans un seul fichier.

Distinguons bien qu’il peut travailler en environnement de développement, et de production. La différence est qu’en développement des optimisation comme la minification des fichiers JS n’est pas faite.

Le fichier webpack.config.js

Dans le fichier webpack.config.js, y sont logées les informations de configuration pour désigner les fichiers sources, et cibles. La variable Encore de portée globale porte les configurations pour Webpack. SetOutputPath indique le répertoire qui contient les fichiers JS bundlés et le fichier CSS compilé. addEntry indique le fichier de départ du processus de compilation.

La dernière ligne Javascript expose l’API de Encore, ainsi le fichier qui veut utiliser le module Encore pourra utiliser la fonction getWebpackConfig().

var Encore = require('@symfony/webpack-encore');
// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

Encore
    // directory where compiled assets will be stored
    .setOutputPath('public/build/')
    // public path used by the web server to access the output path
    .setPublicPath('/build')
    // only needed for CDN's or sub-directory deploy
    //.setManifestKeyPrefix('build/
   .addEntry('app', './assets/js/app.js')
    //.addEntry('page1', './assets/js/page1.js')
    //.addEntry('page2', './assets/js/page2.js')

    // When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
    .splitEntryChunks()

    // will require an extra script tag for runtime.js
    // but, you probably want this, unless you're building a single-page app
    .enableSingleRuntimeChunk()
    .cleanupOutputBeforeBuild()
    .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())
    // enables hashed filenames (e.g. app.abc123.css)
    .enableVersioning(Encore.isProduction())

    // enables @babel/preset-env polyfills
    .configureBabel(() => {}, {
        useBuiltIns: 'usage',
        corejs: 3
    })

    // enables Sass/SCSS support
    .enableSassLoader()
   // uncomment if you use TypeScript
    //.enableTypeScriptLoader()

    // uncomment to get integrity="..." attributes on your script & link tags
    // requires WebpackEncoreBundle 1.4 or higher
    //.enableIntegrityHashes(Encore.isProduction())

    // uncomment if you're having problems with a jQuery plugin
    //.autoProvidejQuery()

    // uncomment if you use API Platform Admin (composer req api-admin)
    //.enableReactPreset()
    //.addEntry('admin', './assets/js/admin.js')
;

module.exports = Encore.getWebpackConfig();

Ci-dessus est le fichier par défaut, tel que préconfiguré, la ligne .enableSassLoader() a été décommentée pour activer le support de Sass.

Compiler et bundler avec Webpack

Lancez la commande suivante pour compiler :

yarn encore dev
yarn run v1.17.0
$ /Users/myuser/sites/newsymfony/node_modules/.bin/encore dev
Running webpack ...

 DONE  Compiled successfully in 1355ms                                                                                                 15:15:00

 I  4 files written to public/build
Entrypoint app [big] = runtime.js vendors~app.js app.css app.js
✨  Done in 14.83s.

Il y a 4 fichiers générés dont app.css et app.js, mais aussi runtime.js et vendors~app.js.

runtime.js est le fichier de Webpack disponible dans le répertoire public, eh oui une fois sur le client, vous n’avez plus NodeJS, mais ce fichier qui prend en charge le bootstrap de l’application JS.

vendor~app.js contient les bibliothèques JS externe comme bootstrap.js. Jquery.js y sera aussi si vous l’incluez. Donc outre les fichiers JS dans le répertoire assets/css et assets/js, Webpack va prendre les fichiers dans le répertoire node_modules et les mettre dans vendor~app.js pour ne pas les mélanger avec les scripts JS de votre application.

Le point important est l’entry point, qui est le fichier app.js, à partir duquel tout est fait.

// assets/app.js
/*
 * Welcome to your app's main JavaScript file!
 *
 * We recommend including the built version of this JavaScript file
 * (and its CSS file) in your base layout (base.html.twig).
 */

// any CSS you require will output into a single css file (app.css in this case)
require('../css/app.css');

// Need jQuery? Install it with "yarn add jquery", then uncomment to require it.
// const $ = require('jquery');

console.log('Hello Webpack Encore! Edit me in assets/js/app.js');

const $ = require('jquery');
// this "modifies" the jquery module: adding behavior to it
// the bootstrap module doesn't export/return anything
require('bootstrap');

// or you can include specific pieces
// require('bootstrap/js/dist/tooltip');
// require('bootstrap/js/dist/popover');

$(document).ready(function() {
    $('[data-toggle="popover"]').popover();
});

Vous pouvez mettre un fichier Sass

Maintenant que vous avez Node-sass, vous pouvez mettre dans le répertoire assets/css un fichier Sass et il sera pris en compte si vous mettez dans app.js la référence à ce fichier Scss

require('../css/global.scss');

Notez que Symfony 4 nous fournit un outil qui est un wrapper de Webpack, donc il est normal de ne pas avoir de commande comme npm run build que vous aurez si vous travaillez directement avec Webpack, ce que je vous conseille pour faire connaissance avec Webpack, avant de travailler avec Encore. Ce dernier est en quelque sorte un outil prémâché pour que les développeurs Back End puissent prendre en main assez rapidement Webpack sans trop perdre de temps.

Si vous vous intéressez à devenir développeur FullStack, (un vrai 🙂 ) je vous conseille de voir la vidéo d’introduction à Webpack qui explique assez bien la prise en main de l’outil, il y a 3 vidéo à regarder. Vous devez aussi lire un peu sur les modules Javascript, qui sont à la base.

Si vous modifiez le fichier webpack.config.js, il faut relancer

yarn run encore dev

Pour augmenter votre productivité, vous avez la commande suivante qui recompile à chaque fois que vous sauvegardez des fichiers

yarn encore dev --watch

Par contre comme dit précédemment si vous modifiez le fichier webpack.config.js il faut redémarrer. Pour compiler pour la production, la différence étant que le JS sera minifié, faites la commande suivante :

yar encore production

Intégrez les fichiers compilés dans votre template HTML

Enfin la raison d’être de tout ça : nous allons voir le bout du tunnel ! les fichiers générés doivent être inclus dans le HTML, en l’occurence pour Symfony, nous travaillons avec Twig.

<!DOCTYPE html>
<html>
    <head>
        {% block stylesheets %}
            {# 'app' must match the first argument to addEntry() in webpack.config.js #}
            {{ encore_entry_link_tags('app') }}
                 <!--Render <link rel="stylesheet" href="/build/app.css"> -->
        {% endblock %}
    </head>
    <body>
        {% block javascripts %}
            {{ encore_entry_script_tags('app') }}
            <!-- Renders app.js & a webpack runtime.js file
                <script src="/build/runtime.js"></script>
                <script src="/build/app.js"></script> -->
        {% endblock %}
    </body>
</html>

Avec Encore, nous incluons avec des fonctions déjà faites (ce qui ne vous empêche pas de le faire en dur). Les deux liens vers le CSS et le Js sont ajoutés aux blocks.

Si vous ne voulez pas vous farcir tout ce process de build front End, allez-y classiquement avec une inclusion de fichier CSS et JS.

Important à retenir

Ce qui important à retenir, c’est que c’est le fichier app.js qui sert de point d’entrée pour Webpack. Si vous voulez importer Jquery ou Bootstrap c’est dans ce fichier qu’il faut le faire, Webpack va inclure les librairies et créer un bundle pour le JS et CSS. Si vous utilisez Encore, il faut importer (avec Yarn) les librairies, le faire de cette façon va mettre à jour le fichier app.js, vous n’aurez aucun problème d’import de module de cette façon.

yarn add jquery

Seconde chose, les fichiers résultants de la compilation, pour les inclure dans votre template Twig, doivent être dans le template de base base.html.twig afin de faire bénéficier toute l’application web.