Search code examples
javascriptjquerywebpackgulpmaterialize

Materialize $(...).sideNav is not a function using Webpack


I'm currently having an issue with Materialize and Webpack. I'm trying to create two files index-bundle.js and vendor-bundle.js to contain the different javascript files that my project uses. But I keep running into the issue and getting this error TypeError: $(...).sideNav is not a function, I've been trying to figure this one out for a few days now with no luck. If I were to guess it might have something to do with JQuery but I'm unsure. If anyone could help I'd really appreciate it. Thanks

Update: The error changed to TypeError: menu.velocity is not a function after compiling it a few times. Still leads me to believe it has to do with jQuery.

Below are some files that might have some importance.

base.html: https://github.com/MattsLab/MattsLab/blob/master/views/layouts/base.html

webpack.config.js: https://github.com/MattsLab/MattsLab/blob/master/webpack.config.js

Gulp Task:

    gulp.task("scripts:build", () => {
    return gulp.src('assets/scripts/**/*.js')
        .pipe(webpack(require('./webpack.config.js')))
        .pipe(gulp.dest('public'));
});

Webpack.config.js

const path = require('path');
const util = require("gulp-util");
const webpack = require('webpack');

const config = {
    production: process.env.NODE_ENV == "production",
};


module.exports = {
    entry: {
        index: './assets/scripts/app.js',
        vendor: ['jquery/dist/jquery.js', 'materialize-css/dist/js/materialize.js'],
    },
    output: {
        filename: '[name]-bundle.js',
        path: path.resolve(__dirname, 'public/')
    },
    resolve: {
        modulesDirectories: ["node_modules"]
    },
    module: {
        loaders: [{
            loader: "babel-loader",
            include: [
                path.resolve(__dirname, "assets/scripts"),
            ],
            test: /\.js$/,

            query: {
                presets: ['es2015'],
                plugins: ['transform-runtime']
            }
        }, ]
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': config.production ? JSON.stringify('production') : process.env.NODE_ENV
            }
        }),
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery",
            "window.jQuery": "jquery",
            Hammer: "hammerjs/hammer"
        }),
    ]
};

if (config.production) {
    webpackConfig.plugins.push(new webpack.optimize.UglifyJsPlugin({
        sourceMap: false
    }))
}

app.js

$(document).ready(function() {
    $(".button-collapse").sideNav({
        menuWidth: 150
    });
})

Solution

  • After a bit search I was able to solve this issue using following configuration.

    Step 1:

    import Materialize like this:

    import 'materialize-css/dist/js/materialize.js'

    Step 2:

    As mentioned in the original resource:

    MaterializeCSS is not compatible with jQuery 3

    Now, clearly not the best solution but it works. Add reference to older version of jQuery in your html page:

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

    Step 3:

    Add this in your webpack.config file:

    externals: {
      jquery: 'jQuery'
    }
    

    Finally:

    Initialize plugin:

    $('.selector').sideNav();
    

    Original source of answer