Листовка с Webpack в Rails 6. L.timeline не является функцией - PullRequest
0 голосов
/ 09 января 2020

Это похоже на вопрос, который @rossta ответил на Gmaps , но я не понимаю проблему и отвечаю достаточно хорошо, чтобы заставить его предложение работать.

Ошибка: Uncaught TypeError: L.timeline is not a function at Object.success (mapTwo.js:14) Строка 14 - var timelineData = L.timeline(data_data, {. Заполните приведенный ниже код.

Я удалил гемы листовок, которые работают в Rails 5.2 и в консоли

yarn add leaflet
yarn add leaflet.timeline

и код:

// 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

Моя попытка применить решение предлагается:

// 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 Ответ

1 голос
/ 14 января 2020

Есть несколько проблем с вашей настройкой:

  1. Плагин 'leaflet.timeline' предполагает, что модуль листовки доступен как глобальная переменная 'L'. Исходный код плагина показывает, что это правда (на мастере на момент публикации): https://github.com/skeate/Leaflet.timeline/blob/b7a8406f5a9a66ccdbcaf73465baaedadec76d1f/src/Timeline.js#L1
  2. (я полагаю) Вы используете более одной точки входа на страница одновременно: 'application.js' и 'mapTwo.js'. Rails называет точки входа «пакетами», поэтому все в app/javascript/packs является отдельной точкой входа в Webpack. Webpack рекомендует 1 точку входа на страницу ; без дополнительной настройки несколько точек входа на одной странице могут привести к неожиданному поведению, особенно в отношении глобальных переменных (см. # 1).

Чтобы подробнее остановиться на проблеме 2, с вашей текущей конфигурацией, Webpack не знает, что вы хотите использовать две точки входа на странице; он связывает один экземпляр модуля Leaflet в пакете приложений и другой экземпляр модуля Leaflet в пакете mapTwo. Он связывает модуль Leaflet в mapTwo, потому что вы добавили конфигурацию ProvidePlugin L: 'leaflet', которая говорит, в основном, добавляет var L = require('leaflet') к каждому модулю, который ссылается на L.

Так что есть несколько возможных исправлений:

  1. Переместите import 'leaflet.timeline' в mapTwo. js и удалите import 'leaflet' из приложения. js. Вам не нужно import 'leaflet' с учетом вашей конфигурации ProvidePlugin. Это самое простое решение для решения краткосрочной проблемы L.timeline is not a function. Это не мешает вам связывать модули, такие как Leaflet, дважды при использовании нескольких точек входа на странице, например, если вам нужно добавить import 'leaflet' где-нибудь в приложении. js граф зависимостей. ИЛИ

  2. Не разбивайте свои пакеты; консолидировать весь существующий код в графе зависимостей 'application.js'. Возможно, вам понадобится обернуть ваш существующий код mapTwo в обратный вызов, т. Е. document.addEventListener('DOMContentLoaded', callback). ИЛИ

  3. Используйте SplitChunksPlugin , который является способом совместного использования модулей через «чанки» Webpack, что в вашем случае означает запись очки, приложение. js и mapTwo. js. Это означает, что ваш существующий код должен храниться в отдельных пакетах вместе с дополнительными изменениями, более подробно описанными в документации по Rails Webpack: https://github.com/rails/webpacker/blob/master/docs/webpack.md#add -splitchunks-webpack-v4 . Возможно, вам также понадобится обернуть код mapTwo. js в прослушиватель DOMContentLoaded, как в 2.

Наконец, удалите этот код из вашей конфигурации; так как это было скопировано из другого решения, оно не добавляет никакого значения к вашей установке:

environment.loaders.append('leaflet', {
  test: /map/, 
  use: [
    {
      loader: 'imports-loader',
      options: 'this=>window',
    },
  ],
})

Вы также можете комбинировать отдельные группы ProvidePlugin, т. е. вам не нужна отдельная группа для loda sh.

...