I'm trying to make openlayers work in Nuxt but whenever I tried to import openlayers components, I had several errors that I solved, but one of them is "Blob is not defined - node_modules/ol/worker/webgl.js"
I found nothing on openlayers and nuxt and i'm having hard times to just make it work :/
Here is the steps of what I did :
npm install ol
made a file with import View from 'ol/View', got error "can't import ESM module...."
created a plugins folder with a ol.js with all OL assests imported, and added plugins: ['@/plugins/ol'] in nuxt.config
preview of my ol.js file in my plugins folder
Got error "can't read fs" file
added extend: (config, { isDev, isClient }) => { config.node = {fs: 'empty',} into my nuxt.config file in build
Also added standalone: true,
and NOW I have blob is undefined and really, I have no clue on what to do to make openlayers work :/
Any help is welcome !
EDIT : Made some changes
edited nuxt.config
plugins: [{
src: '@/plugins/vuelayers.js',
ssr: false
}, { ... }],
modules: [
...,
'~/shared/vueLayers',
],
Create a file shared/ directory named vuelayers.js
export default function (moduleOptions) {
this.options.css.push('vuelayers/lib/style.css')
}
I have no error but nothing is displayed on my component yet
The "can't import ESM module...." occurs because the ol package exports an ES6 module and when Nuxt is rendered on the server side the parent project uses CommonJS modules. As a result a run time error occurs when the open layers code is not transpiled for server side rendering.
I found there to be two solutions to this problem.
Explicitly transpile the Open Layers modules that are used in the transpile property of the build property in nuxt.config.js
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
transpile: [
'ol/control',
'ol/proj',
'ol/style/Circle',
'ol/style/Fill',
'ol/format/GeoJSON',
'ol/format/MVT',
'ol/Map',
// ...
],
},
Create a Nuxt plug-in to wrap Open Layers that's only used on the client side similar to the example seen in this gist.
I found the second solution to be cleaner and since Open Layers uses <canvas> render the map it can't easily be rendered on the server side anyway.
Note that the Gist linked above is a bit dated, but the idea is still relevant. A modern example might look like the following:
// plugins/open-layers.js
import Map from 'ol/Map';
import View from 'ol/View';
export default (context, inject) => {
const ol = {
Map,
View,
};
inject('ol', ol);
};
// nuxt.config.js
export default {
// ...
plugins: [
{ src: '~/plugins/open-layers.js', mode: 'client' },
],
};
// Parent component
<template>
<client-only>
<Map />
</client-only>
</template>
// Map.vue
<template>
<div ref="map" />
</template>
<script>
export default {
name: 'Map',
methods: {
renderChart() {
this.map = new $ol.Map({
target: this.$refs.map,
view: new $ol.View({}),
});
},
},
};
</script>