问题
This looks just like the question @rossta answered for Gmaps, but I don't understand the problem and answer well enough to make his suggestion work.
The error is: Uncaught TypeError: L.timeline is not a function
at Object.success (mapTwo.js:14)
Line 14 is var timelineData = L.timeline(data_data, {
. Complete code below.
I removed the leaflet gems that work in Rails 5.2 and in console
yarn add leaflet
yarn add leaflet.timeline
and code:
// app/javascript/packs/application.js
import "core-js/stable"
import "regenerator-runtime/runtime"
import '../stylesheets/application'
window.jQuery = $
window.$ = $
import 'leaflet'
import "leaflet.timeline"
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("trix")
require("@rails/actiontext")
require("jquery")
import "bootstrap"
import 'bootstrap/dist/js/bootstrap'
document.addEventListener("turbolinks:load", () => {
$('[data-toggle="tooltip"]').tooltip()
$('[data-toggle="popover"]').popover()
})
<!-- map/index.html.erb -->
<div id="map_two"></div>
<%= javascript_pack_tag 'mapTwo' %>
// javascript/packs/mapTwo.js called from map/index.html.erb
console.log('Hello from /javascript/packs/mapTwo.js')
var mapVar = L.map("map_two", {
center: [34.040951, -118.258579],
zoom: 13
});
L.tileLayer('https://crores.s3.amazonaws.com/tiles/bkm/{z}/{x}/{y}.png').addTo(mapVar);
$.getJSON("map/line_data.geojson", function(data_data) {
var timelineData = L.timeline(data_data, {
style: function(data_data) {
return {
stroke: true,
fillOpacity: 0.5
}
}, // end style: function(data_data)
waitToUpdateMap: true,
onEachFeature: function(data_data, layer) {
layer.bindTooltip(data_data.properties.popup, {
direction: 'top'
});
} // onEachFeature:
}); // end let timelineData = L.timeline
var timelineControl = L.timelineSliderControl({
enableKeyboardControls: true,
steps: 100,
start: 1885,
end: 1928,
});
timelineControl.addTo(mapVar);
timelineData.addTo(mapVar);
timelineControl.addTimelines(timelineData);
}); // end $.getJSON
My attempt at applying the solution offered:
// config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.append('Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
// 'window.Jquery': 'jquery',
Popper: ['popper.js' ,'default'],
L: 'leaflet' // didn't help
}))
// https://stackoverflow.com/questions/59042437/gmaps-with-rails-6-webpack
environment.loaders.append('leaflet', {
test: /map/,
use: [
{
loader: 'imports-loader',
options: 'this=>window',
},
],
})
environment.plugins.append(
'lodash',
new webpack.ProvidePlugin({
_: 'lodash',
})
)
module.exports = environment
package.json
{
"license": "ISC",
"main": "application.js",
"dependencies": {
"@rails/actiontext": "^6.0.0",
"@rails/ujs": "^6.0.1",
"@rails/webpacker": "4.2.2",
"bootstrap": "^4.4.1",
"core-js": "^3.5.0",
"imports-loader": "^0.8.0",
"jquery": "^3.4.1",
"jqueryui": "^1.11.1",
"leaflet": "^1.6.0",
"leaflet.timeline": "^1.2.1",
"lodash": "^4.17.15",
"mapbox": "^1.0.0-beta10",
"ol": "^6.1.1",
"ol-ext": "^3.1.7",
"ol-layerswitcher": "^3.4.0",
"ol-loupe": "^1.0.1",
"popper.js": "^1.16.0",
"regenerator-runtime": "^0.13.3",
"trix": "^1.0.0",
"turbolinks": "^5.2.0",
"webpack": "^4.41.2"
},
"devDependencies": {
"webpack-dev-server": "^3.10.0"
}
}
回答1:
There are a few issues with your setup:
- The
'leaflet.timeline'
plugin assumes the leaflet module is available as the global variable'L'
. The source code of the plugin shows this to be true (on master at the time of this post): https://github.com/skeate/Leaflet.timeline/blob/b7a8406f5a9a66ccdbcaf73465baaedadec76d1f/src/Timeline.js#L1 - (I believe) You are using more than one entry point on the page at one time:
'application.js'
and'mapTwo.js'
. Rails calls entry points "packs", so everything inapp/javascript/packs
is a separate entry point to Webpack. Webpack recommends 1 entry point per page; without extra configuration, multiple entry points on one page can lead to surprising behavior, especially with regards to global variables (see #1).
To elaborate further on issue 2, with your current configuration, Webpack doesn't know you want to use two entry points on the page; it bundles one instance of the Leaflet module in the application pack and another instance of the Leaflet module in the mapTwo pack. It bundles the Leaflet module in mapTwo because you added the ProvidePlugin configuration L: 'leaflet'
, which says, basically, add var L = require('leaflet')
to every module that references L
.
So there are a few possible fixes:
Move your
import 'leaflet.timeline'
into mapTwo.js and removeimport 'leaflet'
from application.js. You don't needimport 'leaflet'
given your ProvidePlugin config. This is the easiest fix to address the short-term issue ofL.timeline is not a function
. It does not prevent you from bundling modules like Leaflet twice when using multiple entry points on the page, say if you were to need to addimport 'leaflet'
somewhere in the application.js dependency graph. ORDon't split up your packs; consolidate all your existing code in the dependency graph of
'application.js'
. You may need to wrap your existing mapTwo code in callback, i.e.,document.addEventListener('DOMContentLoaded', callback)
. ORUse the SplitChunksPlugin, which is a way of sharing modules across Webpack "chunks" which, in your case, means the entry points, application.js and mapTwo.js. This means, keep your existing code in separate packs along with additional changes described in more detail in the Rails Webpack docs: https://github.com/rails/webpacker/blob/master/docs/webpack.md#add-splitchunks-webpack-v4. You may need to also wrap mapTwo.js code in the DOMContentLoaded listener, as in 2.
Finally, remove this code from your configuration; as this was copied from another solution, it's not adding any value to your setup:
environment.loaders.append('leaflet', {
test: /map/,
use: [
{
loader: 'imports-loader',
options: 'this=>window',
},
],
})
You can also likely combine the separate ProvidePlugin groups, i.e., you don't need a separate one for lodash.
来源:https://stackoverflow.com/questions/59670743/leaflet-with-webpack-in-rails-6-l-timeline-is-not-a-function