Les pré-processeur web. Très utile mais loin d'être simple

Jusqu'à récemment, lorsque je travaillait sur un projet web, j'installais les librairies dont j'avais besoin dans leur petit dossier et je les chargeait dans mes pages à grand renfort de <script> ou de <link> selon qu'il s'agissait de CSS ou de Javascript.

Ensuite pour optimiser le nombre de requête, j'ai commencé à réunir les ressources dans des fichiers unique. Seulement c'est long et fastidieux sans compter les problèmes lié au fichier média associé (images ou feuille de styles chargé dynamiquement). Dans certains cas les problèmes surgissant lors d'une tentative de concaténation[1] de fichier sont tel que le gain de performance ne pourra justifier la perte de temps associé.

Et c'est là qu'intervienne les pré-processeur.

Leur but ? effectuer tout un ensemble de tache générique automatiquement. Copie de fichier d'un dossier de travail à un environnement de test ou de production, optimisation d'image, regroupement de scripts, css et autres ressources dans des fichiers uniques, minification[2].

Seulement les type de tache sont nombreuse et les projets ont souvent leur spécificité qui rend la création d'un outil à tout faire prêt à l'emploi quelque peu compliqué. Dans la famille de pré-processeur il y à vraiment beaucoup de choix, Grunt, Gulp, Brunch, ....

J'ai testé Brunch (http://brunch.io/) pendant quelques mois, mais bien que ce soit très facile à mettre en œuvre et que la vitesse de traitement soit impressionnante, l'outil était alors vraiment trop vite limité et ne supportait pas les module node (npm) sans avoir recours à des techniques un peu obscurs qui m'ont causé plus de problème qu'autre chose.[3]

Puis j'ai testé webpack (https://webpack.github.io). Sur le papier tout parait simple et dans la pratique les premiers pas le sont effectivement ... "simple". Bien sur dès que les besoins deviennent plus spécifique il faut prendre son temps et trouver les "loader" [4] adéquat mais même si cela peut parfois semble hardu, j'ai pour le moment toujours trouvé le moyen de plier webpack à mon besoin.

Au final pour bon nombre de cas simple (chargement et concaténation de librairie et de css) je pense que Brunch est l'outil le plus simple à prendre en main et le plus performant en terme de vitesse d’exécution. De de son coté Webpack devrait être plus complet pour ceux qui ont des besoin vraiment très spécifiques.

PS : N'ayant pas testé Brunch dans les versions les plus récentes il est possible que ce dernier soit à présent parfaitement apte à gérer bon nombre de cas insoluble auparavant (le support des paquets NPM change quand même beaucoup de chose)

Pour la comparaison voici un fichier de configuration Webpack utilisé sur un projet (je l'ai même allégé d'une dizaine de ligne).

// helpers
var path = require("path");
var webpack = require("webpack");
// environnement detection
var production = process.argv.indexOf("--production") > -1
    // configuration
module.exports = {
    cache: true,
    context: path.resolve(__dirname, "app"),
    entry: {
        app: "./app.js",
        // -- you could add some additionnal apps
        //app2: "./app2.js",
        // -- if vendor libraries needed to be put together
        vendor: ["jquery", "moment", "jed"]
    },
    output: {
        path: path.resolve(__dirname, production ? "www" : "dev"), // output directory
        filename: "js/[name].js", // output filename
    },
    plugins: [
        // -- put chunck together (here we put all "entry:vendor" librairies into js/vendor.js )
        new webpack.optimize.CommonsChunkPlugin("vendor", "js/vendor.js"),
    ],
    module: {
        loaders: [
            // Po file conversion for JED
            {
                test: /\.po$/,
                loader: 'json!po?format=jed1.x'
            },
            // Babel loader
            {
                test: /\.(js|es6|jsx)?$/,
                loader: 'babel-loader',
                exclude: /node_modules/,
                query: {
                    presets: ['es2015']
                }
            }, {
                test: /\.css$/,
                loader: "style-loader!css-loader"
            }, {
                test: /\.png$/,
                loader: "url-loader?limit=100000"
            }, {
                test: /\.jpg$/,
                loader: "file-loader"
            },
            // expose jquery (eg. required for bootstrap)
            // remove this loader if not necessary
            {
                test: require.resolve("jquery"),
                loader: "expose-loader?$!expose-loader?jQuery"
            },
            // inline base64 URLs for <=8k images, direct URLs for the rest
            {
                test: /\.(png|jpg|gif)$/,
                loader: 'url-loader?limit=8192'
            }
        ]
    },
    // -- build souce map (even in production mode)
    devtool: "#source-map"
};

Et un fichier de configuration Brunch pour faire à peu près la même chose.

exports.config = {
  plugins: {
    babel: {
      presets: ['es2015'],
      ignore: /^(bower_components|vendor)/,
      pattern: /\.(js|es6|jsx)$/
    }
  },
  modules: {
    wrapper: 'commonjs'
  },
  paths: {
    "public": 'dev',
    watched: ['app', 'test', 'vendor', 'scripts']
  },
  files: {
    stylesheets: {
      joinTo: {
        'css/app.css': /^app/
      }
    },
    javascripts: {
      joinTo: {
        'js/vendor.js': /^bower_components/,
        'js/app.js': /^app/
      }
    }
  }
};

Notes

[1] Le terme concaténation, du latin cum et catena, désigne l'action de mettre bout à bout au moins deux chaînes.

[2] c'est un peu le régime minceur pour les ressource web

[3] Depuis la version 2.3.0 sortie en février 2016 les paquets NPM sont géré en natif ce qui devrait régler bon nombre de problème

[4] C'est comme cela que l'on nomme les plugins de webpack

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

Ajouter un rétrolien

URL de rétrolien : https://ldbglobe.fried-rice.net/trackback/6

Haut de page