Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$ is not defined within a .js.erb view using Webpack 2 in Rails app

I'm migrating from assets pipeline to Webpack 2 in a Rails 4 app. Everything seems to work fine, except for the JS code using jQuery within a .js.erb view.

The content of the webpack.config.js is as follows (omitted code for fingerprinting and compression):

const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const jsOutputTemplate = 'javascripts/[name].js'
const cssOutputTemplate = 'stylesheets/[name].css'

module.exports = {
  context: path.join(__dirname, '/app/assets'),
  entry: {
    application: ['./javascripts/application.js', './stylesheets/application.scss']
  },
  output: {
    path: path.join(__dirname, '/public'),
    filename: jsOutputTemplate
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: ['es2015']
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract(['css-loader', 'resolve-url-loader'])
      },
      {
        test: /\.s(a|c)ss$/,
        use: ExtractTextPlugin.extract(['css-loader', 'resolve-url-loader', 'sass-loader?sourceMap'])
      },
      {
        test: /\.(woff2?|svg)$/,
        use: 'url-loader?limit=10000&name=/fonts/[name].[ext]'
      },
      {
        test: /\.(ttf|eot)$/,
        use: 'file-loader?name=/fonts/[name].[ext]'
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: 'url-loader?limit=10000&name=/images/[name].[ext]'
      },
      {
        test: /\.erb$/,
        enforce: 'pre',
        use: 'rails-erb-loader'
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      filename: cssOutputTemplate,
      allChunks: true
    }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      '$': 'jquery',
      'window.$': 'jquery',
      jQuery: 'jquery',
      'jQuery': 'jquery',
      'window.jQuery': 'jquery',
      jquery: 'jquery',
      'jquery': 'jquery',
      'window.jquery': 'jquery'
    })
  ]
}

The jQuery library (and others related) is required within app/assets/javascripts/application.js as follows:

require('jquery');
require('jquery-ui');
require('jquery-ujs');
require('jquery-datepicker');

As you can see, I've used the rails-erb-loader for .erb files but it doesn't work as I might have expected. When the .js.erb file is rendered, I always receive next error in console:

Uncaught ReferenceError: $ is not defined

The code within this file is nothing fancy, only includes some JS calling jQuery's $ function:

let $messagesArea = $('#js-attachments-messages');

However, within console the $ is defined when I print it, even using a debugger at the beginning of the .js.erb:

function $(selector, [startNode]) { [Command Line API] } 

I've included all the possible combinations I've came up to define the jQuery in the plugins section of webpack.config.js:

new webpack.ProvidePlugin({
  $: 'jquery',
  '$': 'jquery',
  'window.$': 'jquery',
  jQuery: 'jquery',
  'jQuery': 'jquery',
  'window.jQuery': 'jquery',
  jquery: 'jquery',
  'jquery': 'jquery',
  'window.jquery': 'jquery'
})

Is there any configuration I have not taken into account?

Any help would be appreciated to resolve this problem.

UPDATE

The content of package.json is as follows:

{
  "devDependencies": {
    "babel-core": "^6.24.1",
    "babel-loader": "^7.0.0",
    "babel-polyfill": "^6.23.0",
    "babel-preset-es2015": "^6.24.1",
    "compression-webpack-plugin": "^0.4.0",
    "css-loader": "^0.28.0",
    "expose-loader": "^0.7.3",
    "extract-text-webpack-plugin": "^2.1.0",
    "file-loader": "^0.11.1",
    "imports-loader": "^0.7.1",
    "node-sass": "^4.5.2",
    "rails-erb-loader": "^5.0.0",
    "resolve-url-loader": "^2.0.2",
    "sass-loader": "^6.0.3",
    "style-loader": "^0.16.1",
    "url-loader": "^0.5.8",
    "webpack": "^2.4.1",
    "webpack-dev-server": "^2.4.4"
  },
  "dependencies": {
    // ...
    "jquery": "^3.2.1",
    "jquery-datepicker": "^1.11.5",
    "jquery-ui": "^1.12.1",
    "jquery-ujs": "^1.2.2",
    // ...
  }
}

UPDATE 2

I've uploaded a sample app reproducing the error trying to remove a resource and then removing it from the page with jQuery.

Sample app

like image 962
backpackerhh Avatar asked May 05 '17 10:05

backpackerhh


1 Answers

I recently had a similar error due to the fact that jQuery required in Webpack is not exposed in the view folder of my app, therefore not visible in my js.erb files. This was solved by exposing jQuery globally adding the following 2 lines in app/javascript/packs/application.js:

import $ from 'jquery';

global.$ = jQuery;

like image 170
CecileV Avatar answered Oct 13 '22 00:10

CecileV