MDB + Webpack guide


Topic: MDB + Webpack guide

Arnt Oddvar Pedersen pro premium priority asked 4 years ago

Edit: Steps removed. See next post for a complete installation guide and boilerplate project.


rhodes bird commented 9 months ago

I appreciate your quality stuff and I would love to read more informative posts like this one. Waves Plugins


Arnt Oddvar Pedersen pro premium priority answered 4 years ago

Material Design Bootstrap + Webpack
Updated: 09/05/2018

 

In this guide we'll walk go through how to quickly set-up a Webpack4 project with MDB jQuery Free and Pro

If you don't want to follow the guide you can also get this entire project directly from GitHub.

 

1. Getting Started
Go into the folder you want to start your new MDB Webpack project in and initialize it:

npm init

Just hit enter through the questions, you can change them later. Once the initialization is done, we're going to setup Babel with the ENV and Stage-0 environments so you can use all the latest stuff in JavaScript and transpile them gracefully to ES5. We are also going to setup ESLint with the Airbnb javascript style guide and add SASS support.

Copy and paste this command into your command line:

npm i --save-dev babel-core babel-eslint babel-loader babel-polyfill babel-preset-env babel-preset-stage-0 clean-webpack-plugin css-loader eslint eslint-config-airbnb eslint-config-airbnb-base eslint-loader eslint-plugin-import exports-loader extract-text-webpack-plugin file-loader html-loader html-webpack-plugin node-sass sass-loader webpack webpack-cli webpack-dev-server

As a pro user, you also want to install the following plugin:

npm i --save-dev copy-webpack-plugin

2. Installing MDB Dependencies
Once the above command(s) are done processing, we're going to install some libraries that are required by MDB. MDB ships with some these already, however Webpack won't be able to find the references for WavesJs and HammerJs so we're installing these as dependencies as well for now. They won't actually be included in the finished product. (No double references)

npm i --save jquery bootstrap popper.js hammerjs node-waves font-awesome

3. Setting up the project
In your project folder, you should now have the following files and folders:

  • package.json
  • node_modules
  • package-lock.json (if using Visual Studio Code)

We're now going to create a few configuration files to tell node, Webpack and ESLint how to function. Create the following files:

  • webpack.config.js
  • .eslintrc
  • .jshintrc (Optional: Only if you use both JSHint and ESLint regularily through Visual Studio Code)

 

Let's also separate our sources, the files we will be actively working on, from the rest of the configuration files. Create this folder:

  • src

You should now have a folder structure that looks something like this image.

 

3.1. Enable ESLint
Open up the ".jshintrc" file and paste the following into it:

{
    "esversion": 6
}

Then open your ".eslintrc" and add the following code to it:

{
  "extends": "airbnb-base",
  "parser": "babel-eslint",
  "env": {
    "browser": true,
    "jquery": true
  }
}

This tells JSHint to not handle error checking in the project and configures ESLint to use the Airbnb javascript style guide as a reference. We also set the environment to "browser" and "jquery" to allow the usage of window and $ commands globally without producing false-positive errors.

3.2 Everyone needs a main page
Finally, inside our sources folder, create an index.html file then paste the following into it:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover">
  <title>Material Design for Bootstrap</title>
</head>
<body>
  <div style="height: 100vh">
    <div class="flex-center flex-column">
      <h1 class="animated fadeIn mb-4">Material Design for Bootstrap</h1>
      <h5 class="animated fadeIn mb-3">Thank you for using our product. We're glad you're with us.</h5>
      <p class="animated fadeIn text-muted">MDB Team</p>
    </div>
  </div>
</body>
</html>

4. Setting up Webpack
Open up webpack.config.js and paste the following into it:

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const extractPlugin = new ExtractTextPlugin({
  filename: 'main.css',
});

module.exports = {
  entry: [
    'babel-polyfill',
    './src/js/index.js',
    './src/scss/main.scss',
    './src/vendors/mdb/scss/mdb.scss'
  ],
  output: {
  path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /.js?$/,
        exclude: [/node_modules/, /vendors/], // Don't lint MDB
        loader: 'eslint-loader',
        options: {
          fix: true,
        },
      },
      {
        test: /.js?$/,
        exclude: [/node_modules/, /vendors/],
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['env', 'stage-0'],
            },
          },
         ],
      },
      {
        test: /.scss?$/,
        use: extractPlugin.extract({
          use: ['css-loader', 'sass-loader'],
        }),
      },
      {
        test: /.html$/,
        use: ['html-loader'],
      },
      // Font-awesome 4.7.X
      {
        test: /.(ttf|otf|eot|svg|woff(2)?)(?[a-z0-9]+)?$/,
        exclude: [/vendors/, /img/],
        loader: 'file-loader?name=fonts/[name].[ext]',
      },
      // MDB Roboto font
      {
        test: /.(ttf|otf|eot|svg|woff(2)?)(?[a-z0-9]+)?$/,
        exclude: [/node_modules/, /img/],
        loader: 'file-loader?name=font/roboto/[name].[ext]',
      },
      {
        test: /.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]',
          useRelativePath: true,
        },
      },
   ],
  },
  plugins: [
    extractPlugin,
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.$': 'jquery',
      'window.jQuery': 'jquery',
      Waves: 'node-waves',
    }),
    new HtmlWebpackPlugin({
      template: 'src/index.html',
    }),
    new CleanWebpackPlugin(['dist']),
  ],
  devtool: 'source-map',
  target: 'web',
};

What's important to notice here is that we're setting the path and name of our compiled (bundles) css file near the very top before we export the settings for Webpack.

We are also telling our entry point where to find the different files; Namely the MDB SCSS file, our main SCSS file, our Javascript entry point and telling Webpack to polyfill ES6 functions where applicable before bundling it all together.

In the "output" entry we are telling Webpack to create a "dist" folder in the same folder as the configuration file and what to name the bundled JS.

 

Unfortunately, Webpack doesn't understand everything so in the rules section; We're telling Webpack what to do when it encounters the different filetypes. At the very top we're telling Webpack to run all encountered JavaScript files not contained within the excluded folders (node_modules and vendors) through ESLint and attempt to auto fix any errors it can before bundling. We're also telling Webpack to transpile any "new" JavaScript (ES6) to ES5 so we can support older browsers.

The next few rules tells Webpack what to do with SASS files, images, fonts and HTML documents and where to place them.

 

 

 

 

Since MDB expects a few global variables, like window.$ and Waves, we're "shimming" a few variables to the global scope through webpack.ProvidePlugin().

With the HTML-Webpack-Plugin, we're defining the main HTML file to use as a template. This tells Webpack to automatically inject the Style and Script tags of our bundled scss and javascript without needing to edit anything ourselves. This is the goal with Webpack.

This plugin is also useful if you end up using a templating engine such as Handlebars as you can dynamically create new pages based on the given template document.

 

With the last plugin, we are telling Webpack to delete the "dist" folder every time you run Webpack in production mode. (npm run webpack --mode production)

 

4.1 Pro users
If you're a PRO user, there are 2 additional things you need to add to your webpack.config.js file. Remember that plugin you installed earlier? Include in in the configuration file:

const CopyWebpackPlugin = require('copy-webpack-plugin');

This is because MDB Pro has an additional "mdb-addons" folder. We need to copy it to the "dist" to avoid getting issues with some Pro functionality.

In the plugins section of the Webpack configuration, copy/paste this:

new CopyWebpackPlugin([{ from: 'src/vendors/mdb/mdb-addons', to: 'mdb-addons' }]),

5. Adding the entry points.
In the Webpack configuration file, we added 2 entry points we haven't created yet. The index.js and main.scss file. Let's create them now.

In the source folder, add a new folder called JS and create a new file inside called index.js (or whatever you ended up calling your entry point). This file brings all your modules together, but for now lets import the libraries needed for MDB. Copy/Paste the following code into index.js

// jQuery
import 'jquery';
// PopperJS
import 'popper.js';
// Bootstrap 4
import 'bootstrap';
// Material Design Bootstrap
import '../vendors/mdb/js/mdb';

The order of things is just as important as when you manually add these scripts in the body of your HTML. You'll notice that we're not importing Node-Waves and HammerJS. Webpack only need these libraries to create references for MDB. Lastly we're importing the non-minified version of MDB to avoid any potential problems.

 

Now, go back to the roof of the source folder and create a new folder called "scss". Inside here, create a new file called "main.scss" and copy/paste this into it:

// FontAwesome 4.7.x
$fa-font-path: '~font-awesome/fonts';
@import '~font-awesome/scss/font-awesome.scss';

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

MDB needs FontAwesome 4 so at the top of our stylesheet we're setting the font path of FA and importing its stylesheet before importing the Bootstrap stylesheet.

 

6. Final Steps
Lastly, let's create some commands. Open up your package.json and remove the already existing "scripts" section, then cop/paste the following into its place:

"scripts": {
  "build": "webpack --mode production",
  "dev": "webpack-dev-server --mode development --open --hot"
},

Open a command promt or terminal and point it to the root folder of your project, then run this command:

npm run dev

If you've followed this guide thoroughly, a browser window should automatically open for you with hot-reloading enabled.

Happy coding!


Arnt Oddvar Pedersen pro premium priority answered 3 years ago

Updated the guide. Removes some unnecessary code and fixed a configuration error on my part with Webpack. This fix allows you to properly import MDB's SCSS files without errors and loads all stylesheets in the correct order.   I've also updated the GitHub repository to reflect all these changes.  The GitHub repository also comes with an example file for how you can split your code and modules by having an optional import "FA5" that enables FontAwesome 5 (Free) together with FontAwesome 4 and shows some sample code in example.js   If you are cloning the GitHub repository as a Pro user, you can simply overwrite the contents of the /src/vendors/mdb/ folder with the contents of your PRO package, and uncomment the CopyWebpackPlugin import at the top of Webpack.Config.js and in the plugins section. See the Readme for a quick walkthrough.

KES pro premium priority commented 1 months ago

May you please provide the link to repository so I will be able to clone it?


Marcin Luczak staff commented 1 months ago

@KES,

Link to the repository can be found in the tutorial made by @Arnt Oddvar Pedersen https://mdbootstrap.com/articles/jquery/md-bootstrap-webpack-tutorial/

Keep coding, Marcin


Michal Szymanski staff answered 4 years ago

Thank you very much for this contribution Arnt!

If you write more comprehensive guide we could attach it to official MDB documentation with your credits.

Best


Arnt Oddvar Pedersen pro premium priority commented 4 years ago

Thank you for the nice comment! I'll publish a more in-depth guide on how to setup the entire webpack environment.

Michal Szymanski staff answered 4 years ago

Wow, that's impressive! Thanks a lot Arnt. I have sent to you an email to clarify a few details. Can you have a look at it? Best,
Awesome! But can be easy using with Webpack 4? For e.g extract-text-webpack-plugin still is for Webpack 3

Arnt Oddvar Pedersen pro premium priority commented 4 years ago

I'm actually using Webpack4 right now! Make sure that you use 4.0.0-beta.0 of extract-text-webpack-plugin as it's compatible with Webpack4. There's also currently a bug I was notified about with the way CSS is currently loaded. Importing the MDB.css file with the extension makes node-sass treat it as a url import and "downloads" it, which makes it load the CSS at the top of the file instead of under Bootstrap's CSS. I'm working on fixing this now.

manchuwook pro answered 3 years ago

I'm a pro user and the npm install using the git url does not include mdb-addons.  Is this an out-of-date tutorial?

Bartłomiej Malanowski staff pro premium commented 3 years ago

you should see "mdb-addons" directory. I can see it using the latest version

londoh pro premium answered 3 years ago

what @manchuwook said: "I'm a pro user and the npm install using the git url does not include mdb-addons. Is this an out-of-date tutorial?" I also dont see it, so is this tutorial out of date, or the folder missing? Or perhaps I am looking in wrong place> - if so please be very specific as to where it is located thanks

Bartłomiej Malanowski staff pro premium commented 3 years ago

If you're using MDB Pro with webpack, you need to copy mdb-addons from your MDB Pro package. Here it's an official tutorial of integrating MDB with Webpack: https://mdbootstrap.com/mdbootstrap-webpack-tutorial/

Hi, I'm using symfony 4 for my projet, I would like to use mdbootstrap for this projet after installing the mdb and all dependencies, i got this error in my console "" TypeError: "exports" is read-only "" i don't access the javascript functionality. Please I want the help


Grzegorz Bujański staff commented a year ago

Hi. check this topic: https://mdbootstrap.com/support/jquery/latest-version-of-mdb-not-compatible-with-webpack/ Here is the configuration for laravel, but maybe it will help you to configure the symfon.


Please insert min. 20 characters.
Status

Answered

Specification of the issue
  • User: Pro
  • Premium support: Yes
  • Technology: MDB jQuery
  • MDB Version: -
  • Device: -
  • Browser: -
  • OS: -
  • Provided sample code: No
  • Provided link: No