Bootstrap datepicker not working with Webpack

Deepan Cool picture Deepan Cool · Aug 7, 2017 · Viewed 11k times · Source

I have created a aspnet core spa project with react using dotnet core spa stater template. I am using the default webpack configuration came with that stater template. I tried to include bootstrap date-picker.

I tried with: npm i bootstrap-datepicker Adding it to entry point and importing it from boot.tsx. It's giving me: $(...).datepicker is not a function

I got the same results with: npm i eonasdan-bootstrap-datetimepicker

I tried with: npm install bootstrap-datepicker-webpack It's giving me: jQuery is not defined

Following is my webpack.config.vendor.js

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = (env) => {
    const extractCSS = new ExtractTextPlugin('vendor.css');
    const isDevBuild = !(env && env.prod);
    return [{
        stats: { modules: false },
        resolve: {
            extensions: ['.js'],
            alias: {
                jquery: Path.join(__dirname, 'node_modules/jquery/dist/jquery')
            }
        },
        module: {
            rules: [
                { test: /\.(svg|woff|woff2|eot|ttf)(\?v=\d+\.\d+\.\d+)?$/, use: 'url-loader?limit=100000' },
                { test: /\.css(\?|$)/, use: extractCSS.extract([isDevBuild ? 'css-loader' : 'css-loader?minimize']) },
                {
                    test: /\.less$/,
                    use: [{
                        loader: "style-loader" // creates style nodes from JS strings
                    }, {
                        loader: "css-loader" // translates CSS into CommonJS
                    }, {
                        loader: "less-loader" // compiles Less to CSS
                    }]
                }
            ]
        },
        entry: {
            vendor: ['bootstrap', 'bootstrap/dist/css/bootstrap.css', 'event-source-polyfill', 'isomorphic-fetch', 'react', 'react-dom', 'react-router-dom', 'jquery', 'font-awesome-webpack', 'bootstrap-datepicker'],
        },
        output: {
            path: path.join(__dirname, 'wwwroot', 'dist'),
            publicPath: '/dist/',
            filename: '[name].js',
            library: '[name]_[hash]',
        },
        plugins: [
            extractCSS,
            new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
            new webpack.DllPlugin({
                path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'),
                name: '[name]_[hash]'
            }),
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': isDevBuild ? '"development"' : '"production"'
            })
        ].concat(isDevBuild ? [] : [
            new webpack.optimize.UglifyJsPlugin()
        ])
    }];
};

Following is my webpack.config.js

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const bundleOutputDir = './wwwroot/dist';

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);
    return [{
        stats: { modules: false },
        entry: { 'main': './ClientApp/boot.tsx' },
        resolve: {
            extensions: ['.js', '.jsx', '.ts', '.tsx']
        },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: '[name].js',
            publicPath: '/dist/'
        },
        module: {
            rules: [
                { test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
                { test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader?minimize' }) },
                { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'file-loader?name=[name].[ext]&outputPath=img/' },
                {
                    test: /\.less$/,
                    use: [{
                        loader: "style-loader" // creates style nodes from JS strings
                    }, {
                        loader: "css-loader" // translates CSS into CommonJS
                    }, {
                        loader: "less-loader" // compiles Less to CSS
                    }]
                }
            ]
        },
        plugins: [
            new CheckerPlugin(),
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./wwwroot/dist/vendor-manifest.json')
            })
        ].concat(isDevBuild ? [
            // Plugins that apply in development builds only
            new webpack.SourceMapDevToolPlugin({
                filename: '[file].map', // Remove this line if you prefer inline source maps
                moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
            })
        ] : [
                // Plugins that apply in production builds only
                new webpack.optimize.UglifyJsPlugin(),
                new ExtractTextPlugin('site.css')
            ])
    }];
};

In the boot.tsx file I have defined the imports like this:

import './css/site.css';
import './css/AdminLTE.css';
import './css/skin-black.css';
import 'jquery';
import './js/morris.js';
import './js/app.js';
import './js/dashboard.js';
import './js/demo.js';
import 'font-awesome-webpack';
import 'bootstrap';
import 'bootstrap-datepicker';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { BrowserRouter } from 'react-router-dom';
import * as RoutesModule from './routes';
let routes = RoutesModule.routes;

Apart from what I have mentioned, I have tried importing the packages in my webpack.config.js, I tried importing the js and css files separately. Nothing worked. I am getting the same error. I tried importing the 3 packages I have mentioned above (the files show only bootstrap-datepicker, but I tried to add all 2 packages). Nothing worked.

Another problem I see is, If I don't import jquery like this

var jQuery = $ = require('jQuery');  

in my custom js files, it's complaining that jquery is not defined, even though it is exported using the webpack.ProvidePlugin. I don't know whether it is a related issue.

Adding alias to the config file is a fix I found in github. I tried with and without it, still getting the same error. Any solutions?

Answer

Yuri Ramos picture Yuri Ramos · Aug 7, 2017

Let's try again making things simple.

1- If a library doesn't fit your needs, after add/installing it you should remove to avoid stack a lot of unused libs.

If you are using npm run: npm uninstall --save moduleName. The --save parameter with update your package.json, don't forget it.

If you are using yarn run: yarn remove moduleName

2- Try every time to seek for libs that are built-in react, probably in the most of the cases there's a lib that suits your need.

suggestion -> https://github.com/Hacker0x01/react-datepicker/

3- Following the suggestion in item 2:

You’ll need to install React and Moment.js separately since those dependencies aren’t included in the package. Below is a simple example on how to use the Datepicker in a React view.

I hope it helped in any way your issue.