Импорт node_modules в Laravel через Mix
Я пытаюсь использовать OpenLayers (v5.3.0) в проекте Laravel 5.7, но у меня много проблем с импортом ol из node_modules.
Я установил ol следующим образом (основываясь на https://www.npmjs.com/package/ol):
npm install ol
Затем я обновил мои ресурсы \js\app.js, которые теперь содержат только следующее:
require('./bootstrap');
require('ol');
РЕДАКТИРОВАТЬ: я также попытался следующее в ресурсах \js\app.js, но безуспешно:
require('./bootstrap');
const ol = require('ol');
Мой webpack.mix.js содержит следующее:
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js/app.js', )
.sass('resources/sass/app.scss', 'public/css');
У меня также есть следующие соответствующие строки в файле с именем map.blade.php, где я хочу отобразить карту OpenLayers:
<script src="{!! mix('js/app.js') !!}"></script>
...
<div id='map' style='z-index: 1; width: 100%; height:calc(100% - 56px);'>
<script>
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
new Map({
target: 'map',
layers: [
new TileLayer({
source: new XYZ({
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
})
})
],
view: new View({
center: [0, 0],
zoom: 2
})
});
</script>
</div>
Я тоже бегал npm run dev
,
При тестировании в Chrome я получаю "Uncaught SyntaxError: Неожиданный идентификатор", ссылаясь на следующую строку в map.blade.php:
import Map from 'ol/Map';
РЕДАКТИРОВАТЬ: я также запустил следующее, чтобы убедиться, что все зависимости установлены:
npm install --save-dev parcel-bundler
Я не получил никаких ошибок при запуске выше, но та же ошибка в Chrome все еще там.
РЕДАКТИРОВАТЬ: я также попытался переместить javascript из моего map.blade.php в новый файл (mapscript.js), а затем импортировать его в map.blade.php (после div 'map') следующим образом:
<script src="{!! asset('js/mapscript.js') !!}" type="module"></script>
Но тогда я получаю следующую ошибку:
Uncaught TypeError: Failed to resolve module specifier "ol/Map". Relative references must start with either "/", "./", or "../".
После этого я попытался переместить следующую строку из app.js и в mapscript.js:
require('ol');
А также попробовал то же самое с:
const ol = require('ol');
Но та же ошибка Uncaught TypeError сохраняется в обоих случаях.
Я пробовал решения многих подобных вопросов в Stack Overflow и в других местах, а также пробовал использовать ol вне npm, но я не нашел ничего, что решило бы эту проблему для меня. Я считаю, что использование npm и Mix - лучший способ встроить OpenLayers в мой проект, но я не могу понять, почему он не работает. Был бы очень признателен за помощь.
0 ответов
После некоторых проб и ошибок у меня OpenLayers 6.1 работает с Laravel 6.2, используя импорт модулей Mix, Webpack и ES6. Хитрость заключается в том, чтобы записать весь ваш javascript в отдельный файл и связать его с app.js.
Установите openlayers в свой проект Laravel с помощью npm:
npm install ol
Создайте новый файл в своем проекте Laravel по адресу resources/js/myMap.js
(рядом с bootstrap.js
а также app.js
) и поместите в него свой javascript-код OpenLayers.
Давайте воспользуемся коротким примером кода, скопированным из официальных документов на https://openlayers.org/en/latest/doc/tutorials/bundle.html.
import 'ol/ol.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
const map = new Map({
target: 'osm_map',
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
center: [0, 0],
zoom: 0
})
});
Нам нужно экспортировать это как буквальный объект, чтобы сделать его доступным для другого кода, поэтому вставьте пять дополнительных строк, как показано ниже.
import 'ol/ol.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
var my_map = { // <-- add this line to declare the object
display: function () { // <-- add this line to declare a method
const map = new Map({
target: 'osm_map',
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
center: [0, 0],
zoom: 0
})
});
} // <-- close the method
}; // <-- close the object
export default my_map; // <-- and export the object
Добавьте эти две строки в конец bootstrap.js
так что он включает наш код и присоединяет наш объект my_map к глобальному объекту окна, чтобы мы могли ссылаться на него со страницы.
import my_map from './myMap.js';
window.my_map = my_map;
Теперь соберите все это, выполнив npm run dev
. Обратите внимание, что мы используем веб-пакет Laravel по умолчанию и смешиваем конфигурации - нам не нужно было редактироватьwebpack.mix.js
вообще.
npm run dev
копирует код в наш myMap.js
файл в app.js
. Нам нужно запускать это каждый раз, когда мы редактируемmyMap.js
. (npm run watch
можно использовать для автоматизации этого шага).
Чтобы карта отображалась в шаблоне лезвия, нам нужно иметь идентификатор div, соответствующий цели OpenLayers Map, osm_map
в нашем примере кода выше. Вот минимальный клинок.
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<style>
#osm_map {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="app">
<div id="osm_map"></div>
</div>
<script src="{{ asset('js/app.js') }}" ></script>
<script type="text/javascript">
window.my_map.display();
</script>
</body>
</html>
Примечание:
- Div id="osm_map" соответствует цели openlayers.
- CSS OpenLayers также был включен в пакет и упоминается здесь. Это стилизует элементы управления OpenLayers.
- Карта отображается, когда мы вызываем наш метод my_map.display().
Это успешно отображает интерактивную карту OpenLayers внутри шаблона лезвия Laravel.
Установить ol
пакет:
npm install ol
Внутри каталога ресурсов в папке js (где существуют bootstrap.js и app.js) создайте файл с именем map.js
resources/js/map.js
Напишите свой код Openlayer в map.js(пример кода):
import 'ol/ol.css';
import {Map,View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
const map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
center: [0, 0],
zoom: 0
})
});
Теперь, goto webpack.mix.js
, обычно в конце.
Добавить .js('resources/js/map.js', 'public/js')
в конце файла
webpack.mix.js
будет выглядеть так:
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.js('resources/js/map.js', 'public/js');
Сейчас же, npm run dev
в терминале
Ваш *.blade.php
код должен быть таким, как следующий пример кода:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Using Webpack with OpenLayers</title>
<style>
#map {
height: 100%;
width: 100%;
left: 0;
top: 0;
overflow: hidden;
position: fixed;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript" src="{{ asset('/js/map.js') }}"></script>
</body>
</html>
Импорт узловых модулей напрямую из общей папки не допускается. Здесь мы импортируем модуль в проект и используем его с помощьюwebpack
в общей папке.
Для производства: npm run production
в терминале