#javascript #reactjs #leaflet
#javascript #reactjs #листовка
Вопрос:
Я использую листовку с Windy в React через CDN, которая работает нормально:
в index.js:
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
<script src="https://api.windy.com/assets/map-forecast/libBoot.js"></script>
Реагирующий компонент:
export const renderMap = (): void => {
const options = {
key: 'xyz',
lat: 41.3,
lon: 2.1,
zoom: 10,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).windyInit(options, (windyAPI: any) => {
const { map } = windyAPI;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).L.popup()
.setLatLng([41.3, 2.1])
.setContent(':)')
.openOn(map);
});
};
Однако я хочу иметь возможность использовать пакет leaflet npm, а не CDN. Когда я импортирую пакет, он определен, но Windy выдает ошибку:
Отсутствует библиотека libBoot.js: 3 листовки
в index.js:
<script src="https://api.windy.com/assets/map-forecast/libBoot.js"></script>
Реагирующий компонент:
import L from 'leaflet';
export const renderMap = (): void => {
console.log('L', L); // defined - object is present
const options = {
key: 'xyz',
lat: 41.3,
lon: 2.1,
zoom: 10,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).windyInit(options, (windyAPI: any) => {
const { map } = windyAPI;
L.popup()
.setLatLng([41.3, 2.1])
.setContent(':)')
.openOn(map);
});
};
Существует очень мало информации о настройке этого онлайн, потому что Windy переносится на Leaflet, а Leaflet переносится на Windy. В кратком руководстве по запуску листовки или в их github нет никакой информации.
Каков правильный способ заставить это работать, используя пакет Leaflet npm
Комментарии:
1. Пожалуйста, попробуйте использовать последнюю версию leaflet поверх cdn
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
, она работает?2. Спасибо @FalkeDesign хорошая мысль. На самом деле это не работает и выдает ошибку, в которой говорится, что требуется версия v1.4.x. Я попробовал версию v1.4.0, и возникает исходная ошибка.
Ответ №1:
Ошибка «Отсутствует библиотека листовки» просто связана с порядком загрузки этих библиотек JS:
https://github.com/windycom/API/tree/master/hello-world#hello-world
Загрузите библиотеку Leaflet в начале вашего скрипта, а затем библиотеку Windy API из URL
https://api.windy.com/assets/map-forecast/libBoot.js
.
- когда вы
<script>
сами явно пишете теги на HTML-странице (чтобы загрузить их через CDN), вы правильно загружаете сначала Leaflet, затем Windy - но когда вы
import
листаете, webpack (который является механизмом сборки по умолчанию при использовании React) связывает его с кодом вашего приложения, и по умолчанию он вставляет<script>
тег последним на<body>
вашей HTML-странице, поэтому он загружается после Windy (который затем выдает сообщение об ошибке) - когда вы повторно вводите свой
<script>
тег для загрузки листовки из своейnode_modules
папки, я предполагаю, что вы сначала возвращаете его обратно (т. Е. Перед тегом Windy); однако это будет работать только в разработке, потому чтоnode_modules
эта папка не будет доступна в производстве.
Самым простым решением для вас было бы, если бы Windy library можно было загружать из локального файла (или пакета npm), а не из его URL (/ CDN): в этом случае вы просто import
добавляете его после Leaflet, и webpack будет связывать их в таком порядке.
Однако вполне вероятно, что Windy сам выполняет какую-то магию в зависимости от своего местоположения, например, для загрузки CSS:
CSS листовки загружается автоматически.
Хотя можно было бы обойти это поведение для CSS, вероятно, оно также выполняет некоторые действия для других вещей (например, доступ к его данным и слоям).
Итак, если мы предполагаем, что мы должны загружать Windy из CDN, но (по какой-либо причине) мы абсолютно готовы к головной боли при загрузке Leaflet из npm (а не из CDN, что, как мы знаем, работает нормально и легко), нам нужно найти способ принудительно загрузить порядок загрузки webpackкаким-то образом.
Теперь мы явно выходим за рамки основного варианта использования webpack, потому что в этой конкретной ситуации мы все еще хотим, чтобы Leaflet был в комплекте, но загружал Windy с URL и после Leaflet, но, очевидно, перед нашим кодом приложения.
Я вижу как минимум 2 возможных (явно хакерских) решения:
- генерируйте
<script>
тег Windy динамически в коде нашего приложения; это гарантирует, что он загружается после Leaflet; но мы должны отложить выполнение части нашего приложения, которая зависит от Windy (например, обернув его в asetTimeout
, в идеале проверив, что Windy теперь доступен, поскольку его задержка загрузки может отличаться) - используйте некоторые плагины webpack для
import
Windy в нашем коде, но фактически webpack все равно загружает его с URL: например, используя dynamic-cdn с определенной конфигурацией для указания URL; не уверен, что было бы легко сохранить правильный порядок загрузки, так как он может не распознать зависимость от Leaflet.
Несмотря на все сказанное, мы все еще можем усомниться в необходимости загрузки Leaflet из npm в этом случае (поскольку загрузка его из CDN перед Windy — это легкий ветерок).
Учитывая приведения any
, которые вам нужно выполнить для Windy, я вижу, что вы на самом деле используете TypeScript. Поэтому вы можете захотеть иметь доступные типы листовок, которые появляются почти естественно, когда вы import
его (и установили @types/leaflet
), создавая впечатление, что он должен быть загружен из npm, чтобы эти типы работали. В этом случае мы можем использовать тот факт, что типы и фактический код времени выполнения — это две разные вещи. В этом случае вы все равно можете import
использовать Leaflet в своем коде и извлекать выгоду из его типа, но указываете webpack, что он не должен быть в комплекте; что вы сделаете его доступным извне, обычно потому, что вы загружаете с CDN. Смотрите опцию externals в webpack. Таким образом, вы получаете лучшее из обоих миров: у вас есть свобода загружать листовку по-своему, здесь явно перед Windy, и у вас все еще есть типы листовок.