简体   繁体   中英

Why is webpack not exposing jQuery as a global?

My project requires a few npm modules, which I'm using yarn and webpack to load in. Namely, they are jquery , bootstrap3 , moment , jquery-tablesort , jquery-ujs , bootstrap-select , and livestamp .

Some of those plugins need jQuery to be exposed as the global $ object. I've tried to make webpack do that, but so far I've failed.

My webpack config currently looks like this:

module.exports = {
  entry: packPaths.reduce(
    (map, entry) => {
      const localMap = map;
      const namespace = relative(join(entryPath), dirname(entry));
      const key = join(namespace, basename(entry, extname(entry)));
      localMap[key] = [resolve(entry)];
      if (entry.includes('vendor')) {
        localMap[key].unshift('babel-polyfill');
      }
      return localMap;
    }, {}
  ),

  output: {
    filename: '[name].js',
    path: output.path,
    publicPath: output.publicPath
  },

  module: {
    rules: [{
      test: require.resolve('jquery'),
      use: [{
        loader: 'expose-loader',
        options: '$'
      }]
    }, ...sync(join(loadersDir, '*.js')).map(loader => require(loader))]
  },

  plugins: [
    new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
    new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
    new ManifestPlugin({
      publicPath: output.publicPath,
      writeToFileEmit: true
    })
  ],

  resolve: {
    extensions: settings.extensions,
    modules: [
      resolve(settings.source_path),
      'node_modules'
    ]
  },

  resolveLoader: {
    modules: ['node_modules']
  }
};

On the advice in this question , I added the module section for expose-loader and removed a previous ProvidePlugin section that I had tried; neither of these options have worked.

My scripts are included like so (in application.html.erb ):

<%= javascript_pack_tag 'vendor.js', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag "//code.highcharts.com/highcharts.js", "chartkick" %>

There are no other scripts included before or after these three. In vendor.js :

import * as $ from 'jquery';

window.$ = window.jQuery = $;

import 'bootstrap3'
import 'moment'
import 'jquery-tablesort';
import 'jquery-ujs';
import 'bootstrap-select';
import 'livestamp';

The manual assignment to window.$ also doesn't work. When Bootstrap loads, it gives me this error:

transition.js:59 Uncaught ReferenceError: jQuery is not defined
    at Object.<anonymous> (transition.js:59)
    at __webpack_require__ (bootstrap bde90632505934e68af9:19)
    at Object.module.exports (npm.js:2)
    at __webpack_require__ (bootstrap bde90632505934e68af9:19)
    at Object.<anonymous> (vendor.js:1)
    at __webpack_require__ (bootstrap bde90632505934e68af9:19)
    at Object.<anonymous> (runtime.js:736)
    at __webpack_require__ (bootstrap bde90632505934e68af9:19)
    at bootstrap bde90632505934e68af9:65
    at vendor.js:69

(Note the vendor.js in the last line of the trace there is the compiled vendor.js, ie not the one included above but the Webpack result.)

What can I do to fix this?

I think in this situation you should use require instead import

Try this in your vendor.js:

window.$ = window.jQuery = require('jquery');

require('bootstrap');
require('moment');
// others...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM