After two days of debugging I finally managed to grasp an issue that I was having on some personal projects ( vue people and others ).
As it stands leaflet used to export itself to the window object, in more recent version they also have an es6 module version.
Most of the leaflet plugins uses the window object so they keep exporting it.
Now there are some edge cases that completely breaks both vue2-leaflet and the plugins if there is a mismatch version from what version vue-leaflet declare is different from the one declared both in the vue-leaflet-plugin and the leaflet-plugin.
I'll make an example with markercluster plugin.
vue-leaflet declare as dependency leaflet: 1.3.4
leaflet.markercluster declare as dependency: leaflet 1.3.1
They are just patch releases so it should be all fine.
What happens instead is that webpack see the two differences and load two leaflet instances.
now everything still works MINUS when:
leaflet markercluster declare a new class say: const a = new LatLngBounds([lat, lon]).
and then uses the leaflet method to check if that bound intersect with other markers.
Since that method check a instanceof LatLngBounds and that LatLngBounds is coming from a DIFFERENT leaflet instance that check will pass false and then everything will start behaving bad / breaking
Everything is fine if all the leaflet versions are set at the same since only one distance of leaflet is instantiated.
@jperelli
EDIT FOR CLARITY:
A solid workaround for this is to use Aliases to point to a single leaflet root instance, for example in nuxt 1.x ( I believe 2.x too ) one would do:
build: {
extend(config){
config.resolve.alias['leaflet'] = path.join(__dirname, 'node_modules/leaflet');
}
}
This explains the problem: https://lexi-lambda.github.io/blog/2016/08/24/understanding-the-npm-dependency-model/
Why use peer dependencies https://stackoverflow.com/questions/26737819/why-use-peer-dependencies-in-npm-for-plugins
@nparley thank you for the links! Here the problem is aggravated by the fact that leaflet uses a class approach and do a lot of checks based on class instances making the debug of the issue a nightmare.
We will need to discuss a solution here, because the vue-plugins import leaflet as a direct dependency.
Version mismatches and double version cause subtle and not subtle errors.
At the moment I think that locking the version should do for a while.
My solution would be:
Complication: leaflet released in 1.3.2 WITHOUT the binding to window.L so we always need to skip that version because it breaks everything.
Note for the future: version 2.0 of vue2-leaflet where we use the module system and every wrapper import only his leaflet counterpart.
Adding unit tests with different leaflet versions would be nice too, to help find out about problems
@nparley yep, Docs and then unit testing is what I would like to do next, but I am not able to proceed on the docs while I am fixing bugs at this rhythm
@lordfuoco Making the same version of leaflet is not solving the issue
@imudin To understand your problem can you please post down all the version of the leaflet related repo that you are using ?
@lordfuoco Now It works. I was using vue2-leaflet-path-transform locally. I added it to my main project in this way npm i /path/to/vue2-leaflet-path-transform. After I published the plugin with [email protected] and [email protected] it is working. Even I updated leaflet of main project to v1.3.4.
@imudin Great! So you are the author of vue2-leaflet-path-transform?
if so please state leaflet as a peerDependecy in your repo ( or not at all ) so that we can avoid this issue in the future
@lordfuoco Okay I will! thank you for your time 馃憤
Hi! Sorry for the delay! I removed the dependendency from vue2-leaflet-markercluster, The package is already published in npm. I'm using import { L } from Vue2Leaflet instead whenever I need it
@lordfuoco thanks!
@jperelli Thank you very much! I am in the process or building up 2.0.0 as a major change were leaflet is a peerDependency, I will try to submit a PR for your plugin to address the Leaflet import :)
ok @lordfuoco! let me know of any help you need. We are working with @marcosfede on upgrading https://github.com/cualbondi/web-buscador to be able to use leaflet's esm (tree shaking) to reduce the size of the bundle.
@jperelli the idea of this 2.0.0 is exactly to enable tree-shaking, where every vue2-leaflet component import only is own counterpart in leaflet
Are you going to set leaflet as a peerDependency in this repo as well? I have vue components that add edit functionality to your components (hopefully I will opensource soon) and was caught by this multiple leaflet issue. edit: adding =>1.0.0 & <2.0.0 for ^1.3.4 similarity
"peerDependencies": {
"leaflet": ">=1.0.0 <1.3.2 || >=1.3.3 <2.0.0"
}
@bytesnz yeas I am in the process to do so, but with leaflet: "^1.3.4"
That will mean it will be able to have peer version of 1.3.2, which you wanted to avoid (https://github.com/KoRiGaN/Vue2Leaflet/issues/281#issuecomment-437692435), didn't you? I adjusted the range above for ^1.3.4 - 1.3.2 https://docs.npmjs.com/misc/semver
@bytesnz according to documentation ^1.3.4 should skip 1.3.2 :
^1.2.3 := >=1.2.3 <2.0.0
Ah yes. Is there any reason not to allow <1.3.2 though?
@bytesnz yep, it's a bugged version where they do not export to window object, and many plugins need it
Only that version is bugged though correct? So using less than 1.3.2 should be fine as well?
@bytesnz correct but we want 1.3.4 because it allow us to implement code splitting
Finally! I was getting a frustrating error whenever I tried to add polylines dynamically.
This workaround fixed it, @lordfuoco could this be added to the docs as a special note? I think it'd help save a lot of people (like me) time with debugging
@ciolt a PR would help :) I am bit swamped with work and behind here
Hi,
I'm using Nuxt 2.4.5 (last version), and I have the error "Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'" when the mouse hover a marker.
I tried to put the workaround alias but it doesn't work
build: {
extractCSS: true,
vendor: ["vue-notifications"],
extend(config) {
config.resolve.alias["leaflet"] = path.join(
__dirname,
"node_modules/leaflet"
);
}
The build says
ERROR path is not defined
@kaboume Add const path = require('path'); at the very top of the same file
Thank you!
After executed "npm install --save path" and added "const path = require("path");" at the top of the nuxt.config.js file, everything works fine.
@ciolt @kaboume did you try the new 2.0 ? it should fix the issue without workaround
No I didn't. I will try. Thank you.
since 2.x is out since a while closing this
Most helpful comment
@nparley thank you for the links! Here the problem is aggravated by the fact that leaflet uses a class approach and do a lot of checks based on class instances making the debug of the issue a nightmare.
We will need to discuss a solution here, because the vue-plugins import leaflet as a direct dependency.
Version mismatches and double version cause subtle and not subtle errors.
At the moment I think that locking the version should do for a while.
My solution would be:
Complication: leaflet released in 1.3.2 WITHOUT the binding to window.L so we always need to skip that version because it breaks everything.
Note for the future: version 2.0 of vue2-leaflet where we use the module system and every wrapper import only his leaflet counterpart.