Импорт 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>

Примечание:

  1. Div id="osm_map" соответствует цели openlayers.
  2. CSS OpenLayers также был включен в пакет и упоминается здесь. Это стилизует элементы управления OpenLayers.
  3. Карта отображается, когда мы вызываем наш метод 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 в терминале

Другие вопросы по тегам