13

I generate a new rails app : rails new titi --webpack=vue

and would like to use jQuery (or other libs like popper, vue-resource...).

I tried to yarn add jquerywhich was fine, but I don't have access to jQuery in my JavaScript code.

In previous Webpacker gem, there was much more conf and I had to write this in shared.js :

module.exports = {
    ...
    plugins: [
      ...
      new webpack.ProvidePlugin({
          $: 'jquery',
          jQuery: 'jquery',
    ]
    ...
    resolve: {
      extensions: settings.extensions,
      modules: [
       resolve(settings.source_path),
        'node_modules'
      ],
      alias: {
        jquery: "jquery/src/jquery",
        vue: "vue/dist/vue.js",
        vue_resource: "vue-resource/dist/vue-resource",
    }
}

What is the cleanest way to include libraries in current Webpacker version ? Something in config/webpacker.yml?

Kikan
  • 281
  • 1
  • 2
  • 8

3 Answers3

21

Updated for Webpacker 3.5.0 and bootstrap@4.1.1

Popper.js and bootstrap@4.0.0 aren't required to install JQuery. However, Bootstrap 4 requires both JQuery and Popper.js, and I assume that is the point of showing them in the original example. Also, I omitted Vue from my example as there is ample documentation on how to add the Vue connections.

To get everything to work, I installed webpack-merge, popper.js, jquery, jquery-ujs, and bootstrap@4.1.1 via Yarn.

Once installed, I was able to update ./config/webpack/environment.js with the following code:

/*
  ./config/webpack/environment.js
  Info for this file can be found
  github.com/rails/webpacker/blob/master/docs/webpack.md
*/

const { environment } = require('@rails/webpacker')
const { merge } = require('webpack-merge')
const webpack = require('webpack')

// Add an additional plugin of your choosing : ProvidePlugin
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
    $: 'jquery',
    JQuery: 'jquery',
    jquery: 'jquery',
    'window.Tether': "tether",
    Popper: ['popper.js', 'default'], // for Bootstrap 4
  })
)

const envConfig = module.exports = environment
const aliasConfig = module.exports = {
  resolve: {
    alias: {
      jquery: 'jquery/src/jquery'
    }
  }
}

module.exports = merge(envConfig.toWebpackConfig(), aliasConfig)

Now that envConfig.toWebpackConfig() is used in the last statement in environment.js, I needed to change development.js, production.js, test.js to the following:

const environment = require('./environment')

module.exports = environment

Then in ./app/javascript/application.js I added the following:

// ./app/javascript/application.js

/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb

console.log('Hello World from Webpacker')

// JS libraries
import "jquery"
import "jquery-ujs"
import "bootstrap"

To make sure JQuery wasn't being loaded via the asset pipeline, I removed the Rails assets connection in ./app/assets/javascripts/application.js:

// require rails-ujs
// require_tree .

I then added these two lines to the header section in ./app/views/layouts/application.html.haml to display the Webpack content:

= stylesheet_pack_tag 'application'
= javascript_pack_tag 'application' 

After making a static_pages controller and static_pages#index view, after starting the Rails server (rails s), I was able to go to my browser's JS console and run console.log(jQuery().jquery); to see if JQuery was loading. Everything loaded as expected.

Documentation can be found here: https://github.com/rails/webpacker/blob/master/docs/webpack.md

John
  • 9,254
  • 12
  • 54
  • 75
sknight
  • 2,009
  • 1
  • 14
  • 15
  • can you confirm that all that's needed now is `import {} from 'jquery-ujs'` [jquery-ujs readme](https://github.com/rails/jquery-ujs#installation-using-rails-and-webpacke) ? – Marklar Jul 07 '18 at 02:47
  • 1
    Are you asking if just importing the jquery-ujs library alone will make JQuery work in a Rails/Webpack project? `jquery-ujs is the unobtrusive implementation to allow you to use jQuery in a Rails app.` If you look on the doc you cited, the first part of the doc https://github.com/rails/jquery-ujs#requirements shows that JQuery is required. I included juery-ujs in this example simply out of habit, as all my previous Rails projects use it as do some of the gems in my projects. If you follow the guide as outlined above, everything will work as expected. – sknight Jul 12 '18 at 17:25
  • I'm still not able to access the Popper functions – Jason FB Apr 15 '20 at 20:26
  • @JasonFB interesting. I'm not sure what versions of things you are using. This content is relatively old (almost 3 years). There might be some changes that I'm not aware of that need to be added or removed. You may be able to simply add the popper library in the application.js before you call `import "bootstrap"`, ie `import "popper"`. You'll have to let us know if it works. :-). If I were setting up a Rails app today, I would use Webpack 4; that setup would likely be different that what's found here. – sknight Apr 16 '20 at 20:05
  • I am just on the latest version of rails 6.0.2 I think trying to install whatever I can. I did not find a resolution to this problem. – Jason FB Apr 17 '20 at 19:01
15

Thanks. That's fine with gem Webpacker 2, but new version of the Gem has a new organisation for files and requires less config.

For Webpack 3, shared.js doesn't seem to be mandatory. Instead, I wrote the config in config/webpack/environment.js like this :

const { environment } = require('@rails/webpacker')

const webpack = require('webpack')

// Add an ProvidePlugin
environment.plugins.set('Provide',  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    jquery: 'jquery',
    'window.Tether': "tether",
    Popper: ['popper.js', 'default'],
    ActionCable: 'actioncable',
    Vue: 'vue',
    VueResource: 'vue-resource',
  })
)

const config = environment.toWebpackConfig()

config.resolve.alias = {
  jquery: "jquery/src/jquery",
  vue: "vue/dist/vue.js",
  vue_resource: "vue-resource/dist/vue-resource",
}

// export the updated config
module.exports = environment
Kikan
  • 281
  • 1
  • 2
  • 8
  • 1
    actually `config.resolve.alias` will not work here, as environment will override default config again. – Simon Iong Dec 16 '17 at 13:22
  • Works for me. I tried for about two hours to get Rails UJS to work with my .js.erb files using jQuery and the `config.resolve.alias` part finally did the trick. – cseelus Apr 19 '18 at 23:14
0

@sknight answer is nice. but I add some missing configuration if you have already not include it.

  1. create application.css file inside app/javascript/packs/application.css otherwise you will get the errors like Webpacker can't find application.css in ~/public/packs/manifest.json. Possible causes:
  2. add import "./application.css"; in app/javascript/packs/application.js
  3. add import "bootstrap/dist/css/bootstrap.css"; in app/javascript/packs/application.js to use the bootstrap class in your templates
Shajed
  • 647
  • 10
  • 14