Posted 8 months ago. Visible to the public. Repeats.

Webpack: How to avoid multiple versions of jQuery

To avoid multiple versions of a package, you can manually maintain a resolutions section in your package.json. We recommend you to do this for packages like jQuery. Otherwise the jQuery library attached to window might not include the functions of your packages that depend on jQuery.

Note: This is only an issue in case you want to use a package functionality from window e.g. $(...).datepicker() from your dev console or any other javascript within the application.

Background

By default yarn will create a folder node_modules that includes all packages and their dependencies. In the example below we see two packages of jQuery. Such duplicates will occur each time no common version could be found or for other reason (like in the example where a common version would have been possible).

yarn.lock

Copy
jquery@2.x: version "2.2.4" resolved "https://registry.yarnpkg.com/jquery/-/jquery-2.2.4.tgz#2c89d6889b5eac522a7eea32c14521559c6cbf02" integrity sha1-LInWiJterFIqfuoywUUhVZxsvwI= "jquery@>=1.7.1 <4.0.0": version "3.4.0" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.0.tgz#8de513fa0fa4b2c7d2e48a530e26f0596936efdf" integrity sha512-ggRCXln9zEqv6OqAGXFEcshF5dSBvCkzj6Gm2gzuR5fWawaX8t7cxKVkkygKODrDAzKdoYw3l/e3pm3vlT4IbQ==

package.json

Copy
{ "dependencies": { "@rails/webpacker": "4.x", "bootstrap-datepicker": "1.8.0", # the package says it needs "jquery": ">=1.7.1 <4.0.0" as a dependency "jquery": "2.2.4", }
Copy
node_modules/jquery node_modules/bootstrap-datepicker/node_modules/jquery

Actual issue

Within the Rails Webpacker config we now provide a jQuery object to boostrap-datepicker:

config/webpack/environment.js

Copy
environment.plugins.prepend( 'Provide', new webpack.ProvidePlugin({ $: 'jquery', jquery: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', }) )

And a jQuery object to window, to have access to jQuery from our dev console or any other javascript within the application.

app/webpack/packs/main.js

Copy
window.$ = jQuery window.jQuery = jQuery

Now this will not allow us to use any functionality from boostrap-datepicker on the window object.

Copy
$('<div></div>').datepicker() // Uncaught TypeError: $(...).datepicker is not a function

Solution

You can maintain a resolutions section within your package.json. This allows you to force the same version of a package for all or an individual package. Another approach (not yet tested) is to set a resolve alias for jquery.

Force all dependencies to use jQuery 2.2.4

Copy
{ "dependencies": { "@rails/webpacker": "4.x", "bootstrap-datepicker": "1.8.0", "jquery": "2.2.4", }, "resolutions": { "jquery": "2.2.4" } }

Force bootstrap-datepicker to use jQuery 2.2.4

Copy
{ "dependencies": { "@rails/webpacker": "4.x", "bootstrap-datepicker": "1.8.0", "jquery": "2.2.4", }, "resolutions": { "bootstrap-datepicker/jquery": "2.2.4" } }

Carvet: Using resolutions will ignore any compatibilities. This might break the packages functionality.

Note: You can use yarn install --flat to find all duplicated packages in your project and add a resolution entry for each. You should throw away the changes in your package.json afterwards, as this approach will not work with real world projects.

References:

Growing Rails Applications in Practice
Check out our new e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Owner of this card:

Avatar
Emanuel De
Last edit:
7 months ago
by Besprechungs-PC
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Emanuel De to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more