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
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
{
"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",
}
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
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: '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
window.$ = jQuery
window.jQuery = jQuery
Now this will not allow us to use any functionality from boostrap-datepicker
on the window
object.
$('<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
{
"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
{
"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.