DEV Community

loading...
Cover image for Vue3 + Vanilla Bootstrap5

Vue3 + Vanilla Bootstrap5

Jay Bertrand
Software architect, fullstack, frontend, backend, middle-end, edge ...
・4 min read

To the non-French readers (🇬🇧, 🇺🇸, 🇳🇿, ...) , this post explains how to integrate Vanilla Bootstrap5 into a Vue3 application. I published a sample project with a detailed README on GitHub. Feel free to ask me questions. Enjoy :)


C'est mon premier post sur dev.to \0/

Bootstrap

Ca fait maintenant plusieurs années que je travaille avec Bootstrap. Pour moi qui ne suis ni graphiste, ni web designer, ni illustrateur, ça me permet d'arriver rapidement à un rendu professionnel pour mes sites pros ou perso. Le « langage » est facile à appréhender, et on trouve des centaines milliers d'exemples de codes et de customisations sur le web.

Single Page Applications

J'aurais peut-être dû commencer par ça : je suis développeur. J'ai œuvré dans des domaines et des technos très différents (programmation système en C/C++, développement de frameworks en Java, applications bureautiques, ...) mais en ce moment, je développe essentiellement des SPAs en Angular 2 5 8 10. Quel rapport avec ce post ? Aucun.

Je n'ai jamais fait de React, je trouve ça un peu fouillis mais vu l'engouement pour ce framework sur les Internets, il ne manque sûrement pas d'intérêt. Je me suis d'ailleurs dit qu'il fallait que j'essaye prochainement ce tuto. Mais toujours pas de lien avec le sujet.

En revanche, je suis désormais officiellement accro à Vue3 😍 La version précédente avait pour avantage d'être légère et facilement intégrable, mais dès que le code grossissait un peu ... 🤮. Cette nouvelle mouture est tout simplement OMG !! Je l'utilise donc de plus en plus pour mes projets et du coup, j'ai voulu y intégrer Bootstrap. Voilà, on y est !

SPA + Bootstrap

Bootstrap étant un peu connu, tous les frameworks hype de création de SPA ont leur binding natif.

Ils ont tous plein d'arguments pour vanter leur mérite : intégrés, configurables, accessibles, modulaires, ... mais parfois, on ne peut pas, ou simplement on ne veut pas utiliser une surcouche.

Maintenant que le cadre est posé, on peut passer aux choses sérieuses.

Intégration

Pour commencer, on part d'un projet Vue3, nouveau ou existant. Ici j'ai créé un projet from scratch en Javascript, mais je vous conseille fortement d'utiliser TypeScript pour vos développements.

Pour pouvoir customiser Bootstrap bien comme il faut, on utilise ses sources au format SASS. Vue gère très bien ce format à condition d'installer le préprocesseur qui va bien, c'est justement le rôle des paquets sass et sass-loader.

Enfin, on installe Bootstrap 5 et ses dépendances (il semble que Popper.js soit obligatoire, pour le moment en tous cas).

# création d'un projet vue3 from scratch
$ npm install -g @vue/cli
$ vue create vue3-with-vanilla-bootstrap5

# pour pouvoir utiliser du SCSS
$ npm i sass-loader sass

# intégration de bootstrap
$ npm i bootstrap@next popper.js

Pour reconfigurer Bootstrap, on crée un fichier src/assets/custom.scss. Son contenu initial est copié de node_modules/bootstrap/scss/bootstrap.scss, le fichier qui bootstrap Bootstrap.

// helpers (ne génèrent pas de contenu)
// doivent être définis en premier
@import "../../node_modules/bootstrap/scss/functions";
@import "../../node_modules/bootstrap/scss/variables";
@import "../../node_modules/bootstrap/scss/mixins";
@import "../../node_modules/bootstrap/scss/utilities";

// notre customisation commence ici

// nouvelle couleur de fond
$body-bg: #ECECEC;

$primary: #F24438;
$secondary: #7C4E40;

// couleurs du thème revisitées
$theme-colors: (
    "primary":    $primary,
    "secondary":  $secondary,
    // ne pas oublier les couleurs de base
    // sinon elles ne seront plus disponibles
    // on peut même en ajouter des nouvelles
    // (tertiary, accent, ...)
    "tertiary":   #515151,
    "success":    $success,
    "info":       $info,
    "warning":    $warning,
    "danger":     $danger,
    "light":      $light,
    "dark":       $dark
);

@import "../../node_modules/bootstrap/scss/root";
// ... autres fichiers scss qui génèrent les règles css
// seulement ceux qui nous intéressent

Dans main.js, on importe notre fichier custom, ainsi que le javascript requis pour les widgets complexes (modal, dropdown, ...) :

// bootstrap javascript
import 'bootstrap'

// bootstrap style
//import 'bootstrap/scss/bootstrap.scss'
import '@/assets/custom.scss'

Et voilà ! Il ne reste qu'à relooker notre application avec les classes bien connues. Attention, la version 5 a fait un grand ménage !

<button type="button" class="btn btn-primary mr-1">Primary</button>

Bouton Primaire Restylé

Et jQuery ?

Bootstrap5 n'embarque plus jQuery, même si à priori on peut encore l'utiliser avec. L'équipe de dév a tout réécrit en pur javascript permettant ainsi de diminuer de manière drastique la taille du bundle final et, je suppose, d'améliorer les performances.

Les widgets évolués (modal, dropdown, ...) sont implémentés par des classes que l'on doit importer. Et pour faire le lien entre les instances et le DOM, on peut bien évidemment utiliser Vue :)

<!-- notez bien l'attribut ref qui nous servira à récupérer la référence au bouton -->
<button ref="popoverRef" id="pop-pop-pop" type="button" class="btn btn-dark" @click="showPopover()">Javascript</button>
import { Popover } from 'bootstrap'

// le lien avec le bouton sera fait automagiquement :)
// ne pas oublier d'exporter cette valeur en sortie de setup()
const popoverRef = ref(null);

const popover = new Popover(popoverRef.value,
    { content: 'Hello world!', placement: 'top' });

popover.show();

Conclusion

Il est tout à fait possible et même relativement facile d'intégrer Bootstrap sans surcouche dans une application Vue, de le customiser et de l'optimiser comme on le ferait pour un site html standard. On évite ainsi d'alourdir le projet avec une librairie supplémentaire, d'avoir à apprendre une nouvelle syntaxe, de noyer notre html dans des balises spécifiques, ...

J'ai publié sur GitHub le projet complet reprenant le code utilisé dans ce article.

A bientôt :)

Discussion (0)