Webpack & Bugsnag

Releases et sourcemaps en production (exemple avec Nuxt)

Difficile d’être serein quand on déploie une app sans être sûr que l’on sera alerté des erreurs rencontrés par les utilisateurs ! De nombreux services comme Sentry ou Rollbar le permettent, pour ma part j’utilise Bugsnag (question de préférences ou de prix). C’est devenu indispensable pour moi, mais c’est toujours aussi complexe à intégrer au tooling et au processus de déploiement continu, donc voici un retour d’expérience d’une mise en place avec Webpack. Attention je ne parle pas ici de comment intercepter les erreurs dans l’app elle-même !

TL;DR : la configuration complète


1️⃣ Installer les plugins

Ajouter les dépendances :

yarn add -D webpack-bugsnag-plugins

Puis les importer dans votre config Webpack :

const { BugsnagBuildReporterPlugin, BugsnagSourceMapUploaderPlugin } = require(‘webpack-bugsnag-plugins’)

2️⃣ Créer une nouvelle release

Pour plus de simplicité, je me base sur le hash du commit courant pour nommer la release, en ajoutant une variable d’environnement temporaire RELEASE au moment du build (ici en utilisant Nuxt) :

"generate": "RELEASE=$(git rev-parse HEAD) nuxt build"

3️⃣ Rapporter la release à Bugsnag

Utilisons le premier plugin fourni par Bugsnag pour l’informer d’une nouvelle release :

new BugsnagBuildReporterPlugin({
apiKey: 'XXX',
appVersion: process.env.RELEASE,
releaseStage: 'production'
})

Si vous utilisez Webpack tel quel, il suffit d’ajouter ce plugin à la propriété plugins de votre configuration : https://webpack.js.org/concepts/plugins/#configuration

Si vous utilisez Nuxt, il faut l’ajouter à la propriété build du fichier nuxt.config.js : https://nuxtjs.org/api/configuration-build#extend

export default {
build: {
extend (config, { isClient }) {
if (!isDev && isClient) {
config.plugins.push(
new BugsnagBuildReporterPlugin({
apiKey: 'XXX',
appVersion: process.env.RELEASE,
releaseStage: 'production'
})
)
}
}
}
}

Notez aussi que seul les fichiers côté client sont concernés, puisque Bugsnag est pensé pour gérer les navigateurs et non pas le serveur. Il est probable de pouvoir gérer les deux, mais je n’en ai pas eu l’utilité donc je n’ai pas testé cet aspect.

4️⃣ Générer les sourcemaps

Les rapports d’erreurs seront peu utiles s’ils renvoient vers les lignes des fichiers compilés et illisibles. Les sourcemaps permettent de lier celles-ci aux lignes de codes correspondantes dans les fichiers source. Webpack les génère automatiquement en ajoutant cette configuration : https://webpack.js.org/configuration/devtool/#devtool

{
"devtool": "#source-map"
}

Avec Nuxt, même principe, on modifie la config à la volée :

export default {
build: {
extend (config, { isClient }) {
if (!isDev && isClient) {
config.devtool = '#source-map'
}
}
}
}

5️⃣ Transférer les sourcemaps

Ne reste plus qu’à transmettre des fichiers à Bugsnag en utilisant le deuxième plugin fourni :

new BugsnagSourceMapUploaderPlugin({
apiKey: 'XXX',
appVersion: process.env.RELEASE,
releaseStage: 'production',
overwrite: true,
})

La propriété overwrite permet d’écraser des fichiers au nom identique. Si vous laissez à false (par défaut), en cas de build identique (si vous déployez deux fois le même commit, ou bien si les fichiers n’ont pas été modifiés), Webpack créera une erreur qui bloquera le processus entier ; donc je conseille de laisser à true à défaut d’une solution plus élégante.

Si vous utilisez Nuxt, comme d’habitude, on modifie la config à la volée :

if (!isDev && isClient) {
config.devtool = '#source-map'
config.plugins.push(
new BugsnagSourceMapUploaderPlugin({
apiKey: 'c1e2241fdaa9785ed9f9288526498ae4',
appVersion: process.env.RELEASE,
releaseStage: 'production',
overwrite: true,
})
)
}

6️⃣ Éviter les sourcemaps lisibles en production

Pour que vos sourcemaps ne soient pas déployés en même temps que le reste de l’app et empêcher les curieux de fouiller trop facilement dans vos fichiers sources, il suffit de les supprimer en fin de script :

"generate": "RELEASE=$(git rev-parse HEAD) nuxt generate && rm dist/**/*.map"

⏭ Résumé

Voilà l’ensemble de la configuration nécessaire pour intégrer Bugsnag à vos build Webpack :


⤴️ Aller plus loin ?

LogRocket est un service complémentaire spécialisé dans le suivi du parcours utilisateur avant que l’erreur apparaisse. C’est un plus qui peut paraître superflu, mais si vous utilisez un gestionnaire d’état (Vuex pour Vue, Redux pour React, etc.) LogRocket permet de garder un historique des mutations. Je n’ai pas encore poussé aussi loin, mais le résultat semble prometteur :