通过Mix将node_modules导入Laravel

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过Mix将node_modules导入Laravel相关的知识,希望对你有一定的参考价值。

我试图在Laravel 5.7项目中使用OpenLayers(v5.3.0),但是从node_modules导入ol时遇到很多麻烦。

我按照以下步骤安装了OL(基于https://www.npmjs.com/package/ol:]

npm install ol

然后我更新了我的resources js app.js,现在仅包含以下内容:

require('./bootstrap');
require('ol');

编辑:我也在resources 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中进行测试时,我在引用map.blade.php中的以下行时得到了“ Uncaught SyntaxError:Unexpected identifier”:

import Map from 'ol/Map';

EDIT:我也运行以下命令来确保已安装所有依赖项:

npm install --save-dev parcel-bundler

运行以上命令时没有出现任何错误,但Chrome中仍然存在相同的错误。

EDIT:我也尝试将javascript从map.blade.php移出到新文件(mapscript.js),然后将其导入map.blade.php(在“ map”之后) div)如下:

<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');

但是在两种情况下都仍然存在相同的未捕获的TypeError。

我已经尝试了在Stack Overflow和其他地方解决了许多类似问题的解决方案,并且我还尝试在npm之外使用ol,但是我没有找到任何可以解决我问题的方法。我相信使用npm和Mix是将OpenLayers构建到我的项目中的最佳方法,但是我无法弄清为什么它不起作用。非常感谢您的帮助。

答案

经过反复试验后,我使OpenLayers 6.1使用Laravel 6.2使用Mix,Webpack和ES6模块导入。诀窍是将所有JavaScript都写在一个单独的文件中,然后将其捆绑到app.js中。

使用npm将openlayers安装到Laravel项目中:

npm install ol

在Laravel项目的resources/js/myMap.js(与bootstrap.jsapp.js一起创建一个新文件,并将OpenLayers javascript代码放入其中。

让我们使用从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';

export const my_map = function() {   // <-- add this line to declare the function
    const map = new Map({
        target: 'osm_map',
        layers: [
            new TileLayer({
                source: new OSM()
            })
        ],
        view: new View({
            center: [0, 0],
            zoom: 0
        })
    });
};                                     // <-- and close the braces
export default my_map();               // <-- and add this line

将这两行添加到bootstrap.js的末尾,以使其合并我们的代码。

require('./myMap.js');
window.my_map = my_map;

现在通过执行npm run dev将其捆绑在一起。请注意,我们使用的是Laravel的默认Webpack和混合配置-根本不需要编辑webpack.mix.jsnpm run dev将我们myMap.js文件中的代码复制到app.js中。每次编辑myMap.js时都需要运行此程序。 (npm run watch可用于自动执行此步骤。)>

要使地图显示在刀片​​模板中,我们需要使div ID与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>

</body>
</html>

注意:

  1. <div id="osm_map"></div>与目标匹配。
  • 我们的app.js文件包含我们的代码和导入的ol模块,已被引用。
  • 宽度和高度为100%,因此地图应填充窗口。更改这些以适合。
  • OpenLayers CSS也被捆绑,此处引用。这将设置openlayers控件的样式。
  • 我们从未真正调用过函数my_map()。
  • 现在所有这些都可以正常工作,并且可以在Laravel刀片模板中成功显示交互式OpenLayers映射,但是我相信有更好的方法来构造它。


    我所描述的不太正确。尽管一切正常,但在ReferenceError: Can't find variable: my_map末尾的window.my_map = my_map;行的每个页面加载bootstrap.js上都会发出JavaScript错误。如果我们删除此行,地图将永远不会显示。

    非常感谢您提供有关如何正确构建此结构的评论。是否可以从客户端javascript标记调用ES6模块功能?

    以上是关于通过Mix将node_modules导入Laravel的主要内容,如果未能解决你的问题,请参考以下文章

    在 laravel 5.4 mix 上添加 jQuery

    laravel5.4的laravel-mix踩坑记

    Vuetify 组件导入问题

    将 node_modules 中的 css 导入到 svelte

    laravel + mix + vue 路由器错误:找不到导出'createStaticVNode'(导入为'_createStaticVNode')

    我应该提交由 laravel mix 生成的 css 和 js 吗?