Optimiser vos compilations avec Gulp, Browserify et Watchify

Browserify

Browserify s’impose de plus en plus comme une solution viable pour développer des scripts JS et proposant une syntaxe calquée sur celle de Node.js. Compiler des scripts avec Browserify est simple. Lors des développements, l’utilisation de Watchify permet de compiler à la volée les fichiers. Malgré ça, lorsque vous souhaitez intégrer votre compilation avec d’autres tâches Gulp (comme compiler des fichiers Less), vous vous heurtez à un problème : comment utiliser watchify en même temps que gulp-watch. Réponse dans cet article !

Tous les exemples sont disponibles dans cette archive.

Utiliser Gulp et Browserify - Level 0

Utiliser Gulp et Browserify est assez simple. Vous pouvez utiliser l’API de Browserify ou aller au plus simple et utiliser gulp-browserify qui va vous permettre de compiler vos fichiers facilement.

1
2
3
4
5
6
7
8
const gulp = require('gulp');
const browserify = require('gulp-browserify');
gulp.task('js', function() {
gulp.src('src/*.js', { read: false })
.pipe(browserify())
.pipe(gulp.dest('./build/'))
});

Le problème que vous rencontrez rapidement est que pour travailler sur vos fichiers et qu’ils soient re-compiler à la volée, vous allez devoir parser tous les fichiers. Ceci est très coûteux. Browserify va devoir charger tous vos fichiers mais également toutes les dépendances que vous utilisez. Plus votre projet va grossir, plus le temps va grimper rapidement. De plus, si vous utilisez des transforms comme Babelify les temps vont gonfler encore plus vite (Liste de tous les plugins disponibles via Babel). Également la liste de tous les transforms de Browserify.

Avant de vous montrez la solution finale, voici à quoi ressemblerait une solution avec le classique gulp-watch.

1
2
3
4
5
gulp.task("watch", function () {
gulp.watch("./src/*.js", ["js"]).on("change", function(event) {
console.log(`File ${event.path} has been ${event.type}`);
});
});

Avec cette solution, à chaque changement d’un de vos fichiers, c’est toute une compilation qui est lancée.

Watchify

Watchify permet de rendre efficace la compilation de vos fichiers avec Browserify. Il va garder en mémoire le résultat de la compilation de chaque fichier (tous les fichiers liés à votre fichier comme les dépendances…).

Lorsqu’un fichier est mis à jour, il met à jour l’empreinte du fichier juste modifiée et génère un bundle sans parser l’intégralité de vos dépendances.

Utiliser Gulp, Browserify et Watchify - Level ∞

Installation des dépendances Node.js

Vous pouvez les installer avec Yarn (si vous êtes vraiment à la page 🙂) !

1
$ yarn add browserify gulp vinyl-buffer vinyl-source-stream watchify --dev

Sinon, c’est que vous utilisez ce bon vieux NPM 🙉

1
$ npm install browserify gulp vinyl-buffer vinyl-source-stream watchify --save-dev

gulpfile.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
"use strict";
const browserify = require("browserify"),
buffer = require("vinyl-buffer"),
gulp = require("gulp"),
path = require("path"),
source = require("vinyl-source-stream"),
util = require("gulp-util"),
watchify = require("watchify"),
src = {
js: "./src/main.js"
},
dest = {
js: "./build/"
};
let bundler;
function bundles(profile) {
if (bundler === undefined) {
if (profile === "watch") {
bundler = watchify(browserify(src.js));
} else {
bundler = browserify(src.js);
}
}
bundle();
}
function bundle() {
let start = new Date().getTime(),
_ = bundler
.bundle()
.on("error", util.log.bind(util, "Browserify Error"))
.pipe(source("main.js"))
.pipe(buffer())
.pipe(gulp.dest(dest.js)),
time = new Date().getTime() - start;
util.log("[browserify] rebundle took ", util.colors.cyan(`${time} ms`), util.colors.grey(`(${src.js})`));
return _;
}
gulp.task("js", bundles.bind(null));
gulp.task("watch", function () {
bundles("watch");
bundler.on("update", bundle.bind(null));
});
gulp.task("default", ["watch", "js"]);

Vous avez là un exemple extrêmement simplifié mais fonctionnel. Ce code pourrait être encore simplifié mais il vous montre une ébauche du code à produire pour gérer un hot-reload efficace.

Pour vous simplifier la tâche, je vous mets à disposition une archive avec un guplfile.js plus complet, qui gère la compilation de fichiers JavaScript avec Babel (et des presets comme ES2015) mais également de fichiers Less tout en gérant les profiles comme développement avec ou sans watch mais également production avec minification !

Conclusion

Il est tout à fait possible d’utiliser Browserify de manière efficace avec Gulp à condition de jouer avec les API. Cela oblige à sortir un peu des sentiers et à se passer des plugins Gulp que l’on utilise habituellement.