Latest version of MDB not compatible with Webpack


Topic: Latest version of MDB not compatible with Webpack

Arnt Oddvar Pedersen pro asked 2 years ago

Expected behavior

When running with Webpack4, being able to compile and run the code

Actual behavior

Missing resource: chart.js

Unable to compile the project and run a hot development preview with webpack-dev-server

Resources (screenshots, code snippets etc.)

https://www.dropbox.com/sh/lbhont99eovge8p/AAA2w9iCh2CzNqSp5TIR4Aama?dl=0

In this Dropbox link, you'll find 2 7zip projects. One running MDB 4.8.11, the latest "stable" version I've been able to use for my projects, and the latest version which has a lot of bugfixes and goodies that I'd like to be able to take advantage of.

The few projects with MDB v4.8.11 has only one issue (bsCustomFileInput reference error), that is easily fixed by re-importing the plugin from MDB and re-referencing to the global scope so MDB finds it.

Beyond that, it has no issues whatsoever in any Node or Webpack environment I've tested it in.

Latest version of MDB and any version above v4.8.11 I've not been able to compile at all. I can get Webpack to extract the sources and bundle it all together, but when you start the project, you get plagued with a million reference errors.

To get started with both projects, open package.json and at the very bottom, replace INPUT_YOUR_TOKEN_HERE with your MDB-Pro oauth2 token, then run the following commands inside the folders;

npm install

Then

npm start

This will look through the entry points, bundle sources and open the projects in a new tab in your active browser, or your browser with a new tab, then load everything.

4.8.11 works without issue, 4.15.0 is missing chart.js so I've pre-installed it as a dependency. It then refuses to load because of TypeErrors from MDB.js: https://i.imgur.com/sB9oWxG.png

Any help resolving this would be highly appreciated.


Grzegorz Bujański staff commented 2 years ago

Hi. Try add MDB via zip (download zip and add to your project) not via NPM. We don't know why, but webpack don't compile js files correctly when you add MDB via NPM


nonayerbiz pro premium priority commented 2 years ago

Hi I've run into the same problem. Do you have a webpack example with the proper/latest imports?


Grzegorz Bujański staff answered 2 years ago

@nonayerbiz I use this config:

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  context: __dirname,
  mode: 'development',
  entry: {
    'bootstrapCSS': path.resolve(__dirname, './src/jq-pro/css/bootstrap.css'),
    'jquery': path.resolve(__dirname, './src/jq-pro/js/jquery.js'),
    'popper': path.resolve(__dirname, './src/jq-pro/js/popper.js'),
    'bootstrapJS': path.resolve(__dirname, './src/jq-pro/js/bootstrap.js'),
    'mdb': [path.resolve(__dirname, './src/jq-pro/scss/mdb-pro.scss'), path.resolve(__dirname, './src/jq-pro/js/mdb.js')],
    'main': [path.resolve(__dirname, './src/app.js'), path.resolve(__dirname, './src/styles.scss')]
  },
  devtool: 'cheap-eval-source-map',
  devServer: {
    inline: true
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].min.js'
  },
  resolve: {
    alias: {
      'jquery': path.resolve(__dirname, './src/jq-pro/js/jquery.js'),
      'popper.js': path.resolve(__dirname, './src/jq-pro/js/popper.js')
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
        filename: 'index.html', //relative to root of the application
        template: path.resolve(__dirname, './src/index.html')
    }),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader'
      },
      {
        test: /\.mjs$/,
        include: /node_modules/,
        type: 'javascript/auto'
      },
      {
        test: /\.(ico|jpg|jpeg|png|gif|svg)(\?.*)?$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[path][name].[ext]',
            context: 'src'
          }
        }
      },
      {
        test: /\.(eot|otf|webp|ttf|woff|woff2)(\?.*)?$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[path][name].[ext]',
          }
        }
      },
      {
        test: /\.s?css$/i,
        use: ['style-loader', 'css-loader', 'sass-loader']
      }
    ]
  },
  externals: {
    'chart.js': 'chart',
    'datatables.net': 'datatables.net',
    'desandro-matches-selector': 'desandro-matches-selector',
    'ev-emitter': 'ev-emitter',
    'fizzy-ui-utils': 'fizzy-ui-utils',
    'get-size': 'get-size',
    'outlayer': 'outlayer',
    './item': 'item',
    'clipboard': 'clipboard',
    'PerfectScrollbar': 'PerfectScrollbar',
  }
};

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": "3.0.0"
      }
    ]
  ],
}

nonayerbiz pro premium priority commented 2 years ago

@Grzegorz Bujański with a few tweaks I was able to get this working. I really appreciate the files you provided. J


Grzegorz Bujański staff commented 2 years ago

I'm glad I could help you. Best, Grzegorz


Arnt Oddvar Pedersen pro commented 2 years ago

@nonayerbiz Have you downloaded the latest version of MDB-Pro from your Orders page and put it in the /src/ folder? Alternatively, check my post under this for another example on how to install and import MDB-Pro as a NPM/node package.


vrivero pro premium answered 2 years ago

Since Im working on a full Laravel app and I don't want to modify the folder structure here is my entire config.

It is working fine except for toastr and date/time picker, both of them are undefined for some reason I can't figure out. I have already tried importing them in the mdb.js file

The trick to make it work was to create a additional mdb.js file like on the boilerplate shared by @Arnt Oddvar Pedersen instead of importing the already built mdb.js file in the node_modules folder

webpack.mix.js

const mix = require('laravel-mix');

mix
    .js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

resources/js/app.js

require('./bootstrap');
require('./mdb');

resources/js/bootstrap.js

try {
    window.Popper = require('popper.js').default;
    window.$ = window.jQuery = require('jquery');
    window.tippy = require('tippy.js/dist/tippy-bundle.umd.js');

    require('bootstrap');
    require('chart.js');
    require('datatables.net');
} catch (e) {}

resources/js/mdb.js

import 'mdbootstrap-pro/src/js/free/forms-free';
import 'mdbootstrap-pro/src/js/free/scrolling-navbar';
import 'mdbootstrap-pro/src/js/free/treeview';
import 'mdbootstrap-pro/src/js/free/wow';
import 'mdbootstrap-pro/src/js/pro/buttons';
import 'mdbootstrap-pro/src/js/pro/cards';
import 'mdbootstrap-pro/src/js/pro/character-counter';
import 'mdbootstrap-pro/src/js/pro/chips';
import 'mdbootstrap-pro/src/js/pro/collapsible';
import 'mdbootstrap-pro/src/js/pro/dropdown/dropdown';
import 'mdbootstrap-pro/src/js/pro/dropdown/dropdown-searchable';
import 'mdbootstrap-pro/src/js/pro/file-input';
import 'mdbootstrap-pro/src/js/pro/material-select/material-select';
import 'mdbootstrap-pro/src/js/pro/material-select/material-select-view';
import 'mdbootstrap-pro/src/js/pro/material-select/material-select-view-renderer';
import 'mdbootstrap-pro/src/js/pro/mdb-autocomplete';
import 'mdbootstrap-pro/src/js/pro/preloading';
import 'mdbootstrap-pro/src/js/pro/range-input';
import 'mdbootstrap-pro/src/js/pro/sidenav';
import 'mdbootstrap-pro/src/js/pro/smooth-scroll';
import 'mdbootstrap-pro/src/js/pro/sticky';
import 'mdbootstrap-pro/src/js/vendor/addons-pro/chat';
import 'mdbootstrap-pro/src/js/vendor/addons-pro/multi-range';
import 'mdbootstrap-pro/src/js/vendor/addons-pro/simple-charts';
import 'mdbootstrap-pro/src/js/vendor/addons-pro/steppers';
import 'mdbootstrap-pro/src/js/vendor/addons-pro/timeline';
import 'mdbootstrap-pro/src/js/vendor/addons/datatables';
import 'mdbootstrap-pro/src/js/vendor/addons/datatables-select';
import 'mdbootstrap-pro/src/js/vendor/addons/datatables-select2';
import 'mdbootstrap-pro/src/js/vendor/addons/datatables2';
import 'mdbootstrap-pro/src/js/vendor/addons/imagesloaded.pkgd.min';
import 'mdbootstrap-pro/src/js/vendor/addons/jquery.zmd.hierarchical-display';
import 'mdbootstrap-pro/src/js/vendor/addons/masonry.pkgd.min';
import 'mdbootstrap-pro/src/js/vendor/addons/rating';
import 'mdbootstrap-pro/src/js/vendor/free/chart';
import 'mdbootstrap-pro/src/js/vendor/free/chartjs-datalabels';
import 'mdbootstrap-pro/src/js/vendor/free/enhanced-modals';
import 'mdbootstrap-pro/src/js/vendor/free/jquery.easing';
import 'mdbootstrap-pro/src/js/vendor/free/velocity';
import 'mdbootstrap-pro/src/js/vendor/free/waves';
import 'mdbootstrap-pro/src/js/vendor/pro/jarallax';
import 'mdbootstrap-pro/src/js/vendor/pro/jarallax-video';
import 'mdbootstrap-pro/src/js/vendor/pro/jquery.sticky';
import 'mdbootstrap-pro/src/js/vendor/pro/lightbox';
import 'mdbootstrap-pro/src/js/vendor/pro/ofi';
import 'mdbootstrap-pro/src/js/vendor/pro/scrollbar';
import 'mdbootstrap-pro/src/js/vendor/pro/scrolling-navbar';
import 'mdbootstrap-pro/src/js/vendor/pro/toastr';
import 'mdbootstrap-pro/src/js/vendor/pro/vector-map';
import 'mdbootstrap-pro/src/js/vendor/pro/vector-map-world-mill';

global.bsCustomFileInput = require('mdbootstrap-pro/src/js/vendor/free/bs-custom-file-input');

This is how my scrips commands look (unmodified)

"scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},

vrivero pro premium commented 2 years ago

Managed to get toastr to work by replacing

import 'mdbootstrap-pro/src/js/vendor/pro/toastr';

with

window.toastr = require ('mdbootstrap-pro/src/js/vendor/pro/toastr');

Now the only thing left is date/time picker


Arnt Oddvar Pedersen pro commented 2 years ago

Thanks for this bugfix! I'll get updated on the repository ASAP. I've been toying with the Time and Date picker for a few days. I know that it doesn't work in the current version on GitHub I've not imported the files. (Gives an error otherwise)

Hopefully within the next couple of days I can get it working properly.


vrivero pro premium commented 2 years ago

So I also managed to solve the datepicker issue by including the following on webpack config file

resolve: {
    alias: {
        picker: "mdbootstrap-pro/src/js/pro/picker",
    }
}

For whoever is using laravel-mix like me:

mix.webpackConfig({
    resolve: {
        alias: {
            picker: "mdbootstrap-pro/src/js/pro/picker",
        }
    }
})

Arnt Oddvar Pedersen pro commented 2 years ago

Thank you so much for the help with fixing that. I hadn't thought of adding it as an alias to Webpack itself. Updating the main repo now with the fix. I updated it earlier today as well with the new SideNav and adding the toastr fix.


Arnt Oddvar Pedersen pro commented 2 years ago

And the new MDB 4.19.0 update is live in mdb-boilerplate with all features fully working again for Webpack and no-conf projects thanks to the fix you provided vrivero. :)

If you'd like me to include support for laravel-mix @vrivero shoot me a email at arnt.o.pedersen [at] gmail.com with a config file, or add me on Discord (Dizzzy#0072).


I've essentially come up with an alternative solution to installing MDBootstrap as a NPM package that allow you to freely use any kind of package bundler and transpiler of choice.

https://gist.github.com/SpellCraft/0173a3921a1454a7184178c9da60b363

This gist contains:

  • Webpack v4 configuration file (I use this currently in production)
  • package.json (minimal install with Webpack, Babel, ESLint, AirBNB style-guide and prettier)
  • ESLint rules
  • Prettier rules
  • Babel v7 configuration
  • Starter SCSS file to get FontAwesome5 Free & MDB Free/Pro to work as a NPM module

Basically, Webpack doesn't like the way MDB has exported their files, so re-building it (like seen in mdb.js in the gist) makes everything work again.

So far I've tested most of the javascript and components of the MDB Pro package without any issues.


Grzegorz Bujański staff commented 2 years ago

Hi. Thank you for this config. We will test it.


This sounds great!

Anyhow the gist is not available under the link you provided: https://gist.github.com/SpellCraft/0173a3921a1454a7184178c9da60b363 Can you please share it again? I have been struggling with this setup for so long!

Best, Grischa


Grzegorz Bujański staff commented 2 years ago

Unfortunately @Arnt Oddvar Pedersen shared this solution and apparently already removed it. And we unfortunately don't have a copy of this solution


Arnt Oddvar Pedersen pro commented 2 years ago

I apologise for not replying sooner!

I'm working on re-writing the Github repository I made for mdb-boilerplate and webpack with the solution.

https://github.com/SpellCraft/mdb-boilerplate

Should be updated sometime today or tomorrow at the latest. :)


Grzegorz Bujański staff commented 2 years ago

Great. Thanks for that!


mark-steven-au pro premium commented 2 years ago

https://github.com/SpellCraft/mdb-boilerplate

Works a treat including Pro version thanks!


vrivero pro premium answered 2 years ago

How should I implement this into laravel-mix?


Hello! I did a quick google-search as I haven't used Laravel-mix at all, but it looks like Laravel-mix is doing the exact same thing as the webpack.conf.js file from the mdb-boilerplate repository, though they provide their own methods.

To make Laravel-mix work with the current setup, you could simply create a new webpack configuration file named webpack.mix.js with the following content:

const mix = require('laravel-mix');

mix
  .js('src/js/vendor/main.js', 'dist/js')
  .js('src/js/app.js', 'dist/js')
  .sass('src/scss/vendor/main.scss', 'dist/css')
  .sass('src/scss/app.scss', 'dist/css');

Then, append the following switch to all the script commands in package.json:

--config=webpack.mix.js

The script commands should look like this now:

"scripts": {
  "start": "webpack-dev-server --mode development --progress --color --config=webpack.mix.js",
  "dev": "webpack-dev-server --mode development --progress --color --config=webpack.mix.js",
  "prod": "webpack --mode production --config=webpack.mix.js",
  "build": "webpack --mode production --config=webpack.mix.js"
},

I'm still working on updating the README.md of the mdb-boilerplate repository, giving it some much needed T.L.C., but I hope my experimental configuration above works out for you. Do note that I haven't tested this out myself, but from reading the online documentation, this is all that you need and the changes that you need to make for it to work.

If it works out for ya, I'd appreciate some feedback so I can include this into the updated README file!


Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Answered

Specification of the issue
  • User: Pro
  • Premium support: No
  • Technology: MDB jQuery
  • MDB Version: 4.15.0
  • Device: N/A
  • Browser: Firefox, Chrome, Edge
  • OS: All
  • Provided sample code: No
  • Provided link: Yes