Webpack + Customizable Bootstrap 4.x (SCSS)

Published on Author Artem Butusov12 Comments

Install Bootstrap 4

Please note, Bootstrap 4 requires peer dependencies jquery and tether (for alpha) or popper.js (for beta+).

Alpha instructions:

npm --save install bootstrap@next jquery tether

Beta+ instructions:

npm --save install bootstrap@next jquery popper.js

Create local Bootstrap 4 configuration

We need to import base Bootstrap 4 configuration and be able to remove some components to make js/css library lighter and also we need to be able to override any variable, mixin etc.

Create directory src/bootstrap which will containt js/css import and overrides.

Main js import file src/bootstrap/bootstrap.js should match with node_modules/bootstrap/Gruntfile.js babel section.

Create js import file src/bootstrap/bootstrap.js:

// If you don't have ES6 transpiler or have TypeScript then you could use distributed version but will loose module customization
import 'src/bootstrap/dist/js/bootstrap';

// If you have ES6 transpiler then you could code below and will be able to customize what modules will be included in the build.
/*
import 'bootstrap/js/src/alert';
import 'bootstrap/js/src/button';
import 'bootstrap/js/src/carousel';
import 'bootstrap/js/src/collapse';
import 'bootstrap/js/src/dropdown';
import 'bootstrap/js/src/modal';
import 'bootstrap/js/src/popover';
import 'bootstrap/js/src/scrollspy';
import 'bootstrap/js/src/tab';
import 'bootstrap/js/src/tooltip';
*/

Main css import file src/bootstrap/bootstrap.scss should be a slightly tuned version of default main import file located in node_modules/bootstrap/scss/bootstrap.scss.

Create css import file src/bootstrap/bootstrap.scss:

// Site overrides
@import "variables";

// Core variables and mixins
@import "~bootstrap/scss/custom";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";

// Reset and dependencies
@import "~bootstrap/scss/normalize";
@import "~bootstrap/scss/print";

// Core CSS
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
@import "~bootstrap/scss/code";
@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";

// Components
@import "~bootstrap/scss/animation";
@import "~bootstrap/scss/dropdown";
@import "~bootstrap/scss/button-group";
@import "~bootstrap/scss/input-group";
@import "~bootstrap/scss/custom-forms";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
@import "~bootstrap/scss/card";
@import "~bootstrap/scss/breadcrumb";
@import "~bootstrap/scss/pagination";
@import "~bootstrap/scss/tags";
@import "~bootstrap/scss/jumbotron";
@import "~bootstrap/scss/alert";
@import "~bootstrap/scss/progress";
@import "~bootstrap/scss/media";
@import "~bootstrap/scss/list-group";
@import "~bootstrap/scss/responsive-embed";
@import "~bootstrap/scss/close";

// Components w/ JavaScript
@import "~bootstrap/scss/modal";
@import "~bootstrap/scss/tooltip";
@import "~bootstrap/scss/popover";
@import "~bootstrap/scss/carousel";

// Utility classes
@import "~bootstrap/scss/utilities";

Create test override

Create test override in src/bootstrap/_varibales.scss:

$enable-flex: true;
$brand-primary: #710000;

HTML to test if bootstrap overrides are working well:

<button class="btn btn-primary">Button should be red</button>

Import Library

Import tether and bootstrap custom import main files somewhere in src/main.js or src/index.js:

// Tether (required for Bootstrap 4.x Alpha)
// import 'tether';
// import 'tether/src/css/tether-theme-basic.sass'; // optional

// Popper.js (required for Bootstrap 4.x Beta+)
// Popper is auto imported by Bootstrap JS modules where it is needed

// Bootstrap 4.x
import './bootstrap/bootstrap';
import './bootstrap/bootstrap.scss';

Webpack Configuration

We need autoprefixer, scss and ES6 transpiler (optionally, for custom js library build) to be able to build Bootstrap 4.

JQuery (and Tether for Bootstrap v4.x Alpha) should be properly exported into globals.

webpack.config.js:

var webpack = require('webpack');

var sassLoader = isDevServer
  ? ['style-loader?sourceMap', 'css-loader?sourceMap', 'postcss-loader?sourceMap', 'sass-loader?sourceMap'].join('!')
  : ExtractTextPlugin.extract(['css-loader?sourceMap', 'postcss-loader?sourceMap', 'sass-loader?sourceMap']);

// autoprefixer configuration based on Bootstrap 4.x ALPHA defaults
// var autoprefixerBrowsers = require('bootstrap/grunt/postcss').autoprefixer.browsers;
// autoprefixer configuration based on Bootstrap 4.x BETA defaults
var autoprefixerBrowsers = require('bootstrap/package.json').browserslist;

var config = {
  ...
  module: {
    loaders: [
      {
        test: /\.(scss|sass)$/,
        loader: sassLoader
      }
    ]
  },
  plugins: [
    new webpack.ProvidePlugin({
      'jQuery': 'jquery',
      'window.jQuery': 'jquery'
      // For Bootstrap 4.x Alpha, for Beta+ is not needed
      // 'Tether': 'tether'
      // 'window.Tether': 'tether'
    }),
  ],
  postcss: function () {
    return [
      require('postcss-flexbugs-fixes'),
      require('autoprefixer')({ browsers: autoprefixerBrowsers })
    ];
  }
};

...

module.exports = config;

Customization

src/bootstrap/bootstrap.js could be used to remove js components from library.
src/bootstrap/bootstrap.scss could be used to remove css components from library.
src/bootstrap/*.scss could be used to alter variables, mixins or components.

Try to keep the same file/folder structure under src/bootstrap as you have under node_modules/bootstrap/scss.

Test Repo

You could see example configuration in https://github.com/sormy/skeleton-react-ts

12 Responses to Webpack + Customizable Bootstrap 4.x (SCSS)

  1. “Create directory src/bootstrap which will containt js/css import and overrides.”

    Are we copying these after they are installed from the node modules directory?

    • We are creating our own files and importing code from node_modules. That will allow us to decouple our changes from mainstream changes and will simplify upgrade for mainstream part.

  2. Thanks for this!

    For anyone stumbling upon this with Webpack 2.x which doesn’t allow passing custom parameters to the config, you can pass those same parameters in a file placed in src/bootstrap/postcss.config.js.

  3. Can you explain the following line:

    var autoprefixerBrowsers = require(‘bootstrap/grunt/postcss’).autoprefixer.browsers;
    Thanks!

Leave a Reply to Artem Butusov Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.