Closed FabianSchmick closed 1 year ago
Hi Fabian,
in this regard I did a quick test in the past.
You can found it listed within the FAQs:
3. How can I import this library as ES module?
Usually, when working with a js bundler like Vite or Webpack, you need to provide to this library the full path to some dynamically imported files from the
srcFolder
:import './your-custom-style.css'; import 'leaflet/dist/leaflet.css'; import L from 'leaflet'; import '@raruto/leaflet-elevation/src/index.js'; import '@raruto/leaflet-elevation/src/index.css'; const map = L.map('map', { center: [41.4583, 12.7059] zoom: 5, }); const controlElevation = L.control.elevation({ // CHANGE ME: with your own http server folder (eg. "http://custom-server/public/path/to/leaflet-elevation/src/") srcFolder: 'http://unpkg.com/@raruto/leaflet-elevation/src/' }).addTo(map); // Load track from url (allowed data types: "*.geojson", "*.gpx", "*.tcx") controlElevation.load("https://raruto.github.io/leaflet-elevation/examples/via-emilia.gpx");
All external dependencies are lazy loaded (by default from unpkg.com) if they are not found within the HTML page before running the leaflet-elevation script (e.g. togoejson, d3js, ..)
π Raruto
Hi @Raruto
Thank you for your quick reply. I didn't see the FAQs. But with your answer, I could resolve the first error:
Uncaught (in promise) Error: Cannot find module 'https://unpkg.com/@tmcw/togeojson@5.6.2/dist/togeojson.umd.js'
The solution was:
import * as L from 'leaflet';
import * as d3 from 'd3';
global.d3 = d3;
import * as toGeoJSON from '@tmcw/togeojson';
global.toGeoJSON = toGeoJSON;
import 'leaflet-geometryutil';
import 'leaflet-almostover';
But I still have the other error
Uncaught (in promise) Error: Cannot find module 'http://localhost/src/handlers/distance.js'
The file is also public, available at http://localhost/src/handlers/distance.js Can I import the handlers by myself and don't use the lazy loading? Or do I need to configure my webpack for this?
If I import the handlers by myself like:
import '@raruto/leaflet-elevation/src/handlers/distance.js';
import '@raruto/leaflet-elevation/src/handlers/time.js';
import '@raruto/leaflet-elevation/src/handlers/altitude.js';
import '@raruto/leaflet-elevation/src/handlers/slope.js';
import '@raruto/leaflet-elevation/src/handlers/speed.js';
import '@raruto/leaflet-elevation/src/handlers/acceleration.js';
It also results in the same error
And if I empty the handlers
:
const controlElevation = L.control.elevation({
handlers: []
}).addTo(map);
I get the error
Uncaught (in promise) Error: Cannot find module 'http://localhost/src/components/summary.js'
If I add the following comment /* webpackIgnore: true */
in here:
return condition !== false
? import(/* webpackIgnore: true */ _.resolveURL(src, this.options.srcFolder))
: Promise.resolve();
Everything works with the lazy loading.
Got the comment from https://github.com/webpack/webpack/issues/8341#issuecomment-436550381 maybe this should be added in a PR?
Explanation from https://stackoverflow.com/a/56998596/5947371:
Webpack reinterprets the standard ES import statement. Within a standard webpack config, webpack uses this statement as a split point for bundles, so even modules that are dynamically imported are expected to be there at webpack build time (and the build process will fail if they are not available)
Do I need to configure my webpack?
I'd say it shouldn't be necessary, if you're able to disable lazy loading completely.
Probably the sample code mentioned in the FAQ was tested with Vite (which is overall easier to set up).
Can I import the handlers by myself?
Just prevent the lazy loading logic by providing your own handlers, it should be something like following:
import { Distance } from "@raruto/leaflet-elevation/src/handlers/distance.js";
import { Time } from "@raruto/leaflet-elevation/src/handlers/time.js"
...
handlers: [
Distance,
Time,
...
]
Original source: https://github.com/Raruto/leaflet-elevation/issues/229#issuecomment-1386659536
If you still have problems, try to expose them globally as well:
import { Distance } from "@raruto/leaflet-elevation/src/handlers/distance.js";
import { Time } from "@raruto/leaflet-elevation/src/handlers/time.js"
import '@raruto/leaflet-elevation/src/index.js';
...
L.Control.Elevation.Distance = Distance;
L.Control.Elevation.Time = Time;
...
const controlElevation = L.control.elevation({ ... }).addTo(map);
Related source:
If I add the following comment
/* webpackIgnore: true */
in here, everything works with the lazy loading.Maybe this should be added in a PR?
Within your local code (to apply some patch or quick test), you can always monkey patch any native functionality through the L.Control.Elevation.include()
.
For more info: old issues
π Raruto
@Raruto thank you for your support and help.
I try to prevent the lazy loading logic by providing my own handlers
as you suggested. This works for the files in the handlers
directory. For the files in the components
directory, it will not work, as they still try to get lazy loaded.
But I will stick to the second approach and monkey patch the import
function with the specific webpack comment ππΌ thank you again for the useful tips :)
Ok @FabianSchmick.
When you're done, just to facilitate the searching job for those who will come later, remember to post your final code snippet as well.
π Raruto
Final code:
import * as L from 'leaflet';
import * as d3 from 'd3';
global.d3 = d3;
import * as toGeoJSON from '@tmcw/togeojson';
global.toGeoJSON = toGeoJSON;
import 'leaflet-geometryutil';
import 'leaflet-almostover';
import '@raruto/leaflet-gesture-handling/dist/leaflet-gesture-handling';
import '@raruto/leaflet-elevation/libs/leaflet-edgescale.min.js';
import * as _ from '@raruto/leaflet-elevation/src/utils';
import '@raruto/leaflet-elevation/dist/leaflet-elevation';
let map = L.map('map', {
center: [41.4583, 12.7059],
zoom: 5,
});
L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Data © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>'
}).addTo(map);
// Monkey patch the import function -> https://leafletjs.com/examples/extending/extending-1-classes.html#lclassinclude
L.Control.Elevation.include({
import: function(src, condition) {
if (Array.isArray(src)) {
return Promise.all(src.map(m => this.import(m)));
}
switch(src) {
case this.__D3: condition = typeof d3 !== 'object'; break;
case this.__TOGEOJSON: condition = typeof toGeoJSON !== 'object'; break;
case this.__LGEOMUTIL: condition = typeof L.GeometryUtil !== 'object'; break;
case this.__LALMOSTOVER: condition = typeof L.Handler.AlmostOver !== 'function'; break;
case this.__LDISTANCEM: condition = typeof L.DistanceMarkers !== 'function'; break;
case this.__LEDGESCALE: condition = typeof L.Control.EdgeScale !== 'function'; break;
case this.__LHOTLINE: condition = typeof L.Hotline !== 'function'; break;
}
// Add the ignore comment for webpack
return condition !== false ? import(/* webpackIgnore: true */ _.resolveURL(src, this.options.srcFolder)) : Promise.resolve();
}
});
const controlElevation = L.control.elevation().addTo(map);
controlElevation.load('https://raruto.github.io/leaflet-elevation/examples/via-emilia.gpx');
Last step, configure webpack to copy the node_modules/@raruto/leaflet-elevation/src
directory to your public project directory, so the lazy loading can find the requested files.
Example usage with webpack
I can't find a working example or documentation on how to use this plugin with webpack and imports. I have also found #229 which does not help me.
Your environment
Steps to reproduce
Results in an error
What I tried so far
Install (with npm) and import the external libs locally:
Add these in the concatenate process in webpack before my app.js with the map instantiation
I am not allowed to use this library with the calls of external CDN (like unpkg.com), because of General Data Protection Regulations (GDPR). So every external dependency has to be imported locally by my app. Maybe this is another issue?