Search code examples
jquerywebpack-2

jQuery with Webpack 2


My webpack.config.js looks as below :

var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
var node_dir = __dirname + '/node_modules';
const autoprefixer = require('autoprefixer');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');

module.exports = {
  context: path.join(__dirname, "src"),
  devtool: debug ? "inline-sourcemap" : null,
  entry: ['tether',
    'font-awesome-loader',"bootstrap-loader","./js/client.js"],
  resolve: {
    extensions: ['.js', '.styl'],
    alias: {
      'jquery': node_dir + '/jquery/src/jquery.js',
    }
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        loader: 'babel-loader',
        query: {
          presets: ['react', 'es2015', 'stage-0'],
          plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties'],
        }
      },
      { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] },
      { test: /\.scss$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] },
      {
        test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use: 'url-loader?limit=10000',
      },
      {
        test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
        use: 'file-loader',
      },
      {
      test: /\.styl$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'stylus-loader',
          /*options: {
            use: [stylus_plugin()],
          },*/
        },
      ],
    },
      // Use one of these to serve jQuery for Bootstrap scripts:

      // Bootstrap 4
      { test: /bootstrap\/dist\//, use: 'imports-loader?jQuery=jquery' },
    ]
  },
  output: {
    path: __dirname + "/dist/",
    filename: "client.min.js"
  },
  plugins:  [
    //new webpack.optimize.DedupePlugin(),
    //new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery",
      Tether: "tether",
      "window.Tether": "tether",
      Alert: "exports-loader?Alert!bootstrap/js/dist/alert",
      Button: "exports-loader?Button!bootstrap/js/dist/button",
      Carousel: "exports-loader?Carousel!bootstrap/js/dist/carousel",
      Collapse: "exports-loader?Collapse!bootstrap/js/dist/collapse",
      Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
      Modal: "exports-loader?Modal!bootstrap/js/dist/modal",
      Popover: "exports-loader?Popover!bootstrap/js/dist/popover",
      Scrollspy: "exports-loader?Scrollspy!bootstrap/js/dist/scrollspy",
      Tab: "exports-loader?Tab!bootstrap/js/dist/tab",
      Tooltip: "exports-loader?Tooltip!bootstrap/js/dist/tooltip",
      Util: "exports-loader?Util!bootstrap/js/dist/util",
    }),
    new webpack.LoaderOptionsPlugin({
      postcss: [autoprefixer],
    })
  ],
};
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>React, Babel, Webpack 2</title>
  </head>
  <body class="container">
    <div id="app"></div>
    <script src="jquery.timeago.js"></script>
    <script src="client.min.js"></script>
    
  </body>
</html>

But when I try to use jQuery.timeago() function I am getting below error.

enter image description here

I was following React By Example book. When I type window.jQuery I am getting some wierd numbers appearing after jQuery. But when I just type jQuery I am getting undefined. As bootstrap 4 and $.ajax() is working I am sure that jQuery is included but not sure why jQuery shows undifined.

Can anybody explain how jQuery is being included and what am I doing wrong.


Solution

  • Add plugin to plugin section of your webpack config like this:

    var webpack = require('webpack')
    ...
    
    plugins: [
      new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
      })
    ]
    

    EDIT:

    You have cyclic dependency:

    timeago: jquery
    client: timeago jquery
    

    but jquery and client is same bundle. Try to switch of include js bundles in html like this:

    <script src="client.min.js"></script>
    <script src="jquery.timeago.js"></script>
    

    instead of:

    <script src="jquery.timeago.js"></script>
    <script src="client.min.js"></script>
    

    If that does not help or you have another errors you need to extract jquery to separated bundle and include it before timeago. Another way is to include jquery like old school for example from cdn and make webpack know that like this:

    externals: {
      jquery: 'jQuery'
    }
    

    To extract jquery to separated bundle and make it visible for timeago use include sequence like this:

    <script src="common.js"></script>
    <script src="jquery.timeago.js"></script>
    <script src="client.min.js"></script>
    

    And use webpack common chunk plugin like this:

    entry: {
      common: ["jquery"],
      ...
    },
    plugins: [
      new webpack.optimize.CommonsChunkPlugin({
        name: "common",
        filename: "common.js",
        minChunks: Infinity,
      })
    ],