Using Bootstrap 5 with Laravel and Vite

In recent years Tailwind has become the go to CSS solution with new Laravel projects. However there are a lot of Bootstrap sites out there and when working on a recent legacy project it was necessary to update from an old Laravel version and Bootstrap 3 to the latest Laravel and Bootstrap 5.

While moving to latest Laravel could be done in one jump, moving the whole system to Bootstrap 5 was too big, so a strategy was developed to implement Bootstrap 5 progressively.

The legacy site used Blade and @extend. For the Bootstrap 5 pages it was decided to use components and an approach using x-layout. At the same time a number of controller actions were replaced with Livewire. This meant could implement a separate components/layouts/app.blade.php file.

At the same time as updating Bootstrap it was decided would update to use Vite.

Given the approach on the legacy site the strategy used was simple – if destructive.

  • Remove old package.json
  • Get the default package.json for a new Laravel project from GitHub.
{
    "private": true,
    "type": "module",
    "scripts": {
        "dev": "vite",
        "build": "vite build"
    },
    "devDependencies": {
        "axios": "^1.1.2",
        "laravel-vite-plugin": "^0.8.0",
        "vite": "^4.0.0"
    }
}
npm i --save bootstrap @popperjs/core
npm i --save-dev sass
npm install

Then clean up the resources/css and resources/js files. Again in this case the simplest strategy was to remove the existing files (app,js and app.css) and replace with the defaults for a new Laravel site from Github.

Configure vite.config.js

The next step was to configure Vite, this is done in the vite.config.js file, again starting from the default in Github, but adding some simple configuration and note the change to ‘resources/sass/app.scss’.

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

import * as path from 'path';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/sass/app.scss', 'resources/js/app.js'],
            refresh: true,
        }),
    ],
    resolve: {
        alias: {
            "~bootstrap": path.resolve(__dirname, 'node_modules/bootstrap')
        }
    }
});

The default package.json in Laravel configures node as a ‘module’ – see line 3 of the default package.json file. It is therefore necessary to add the line

import path from 'path';

in order to import the path module and access the ‘resolve’ function. Note the Bootstrap web site suggests adding ‘const path = require(‘path’)’ to your vite.config.js however this will fail with an error due to being configured as a module.

Update app.scss

Now it is possible to import bootstrap in your sass/app.scss file.

// Bootstrap
@import '~bootstrap/scss/bootstrap.scss';

Update app.blade.php

Then simply need to add the Vite include in your app.blade.php file.

@vite(['resources/scss/app.scss', 'resources/js/app.js'])

Now all that remains is to run

npm run dev

and your application should now be able to use Bootstrap 5 with Vite and the fantastic instant updates.