Maps in nuxts static mode break
duktiga-havet opened this issue · 10 comments
Hi!
I've been banging my head against this the last few weeks. Maps work great in universal mode but when I run nuxt generate they fall apart - map tiles are spread out on the page instead of being in element, see the screenshot below.
The implementation worked before but broke in an update(?) and I haven't been able to pin down which package yet. I get the same result with google maps in Nuxt and leaflet and google maps in Gridsome so it seems to be a pretty general issue with maps and static.
Has anyone else run into this? Any ideas on how to debug?
try adding around the map
I have the very same issue. @schlunsen what do you mean with "try adding around the map" exactly? Here's my map component
<template>
<div>
<client-only>
<loading class="z-999" :active="loadingMapData" :can-cancel="true" :is-full-page="false" :color="spinnerColor" />
<l-map class="w-full h-3/4" :zoom="zoom" :center="center" :options="options" @click="clearDescription">
<shop-card v-if="shop" :shop="shop" class="absolute left-0 bottom-0 z-999" />
<l-tile-layer :url="tilesUrl" />
<shop-marker v-for="shop in shops" :key="shop.id" :shop="shop" @display-description="displayDescription" />
</l-map>
</client-only>
</div>
</template>
<script>
import ClientOnly from 'vue-client-only'
import Loading from 'vue-loading-overlay'
import ShopCard from '~/components/Map/ShopCard'
import ShopMarker from '~/components/Map/ShopMarker'
import shops from '~graphql/shops'
export default {
apollo: {
shops: {
query: shops
}
},
components: {
ShopCard,
ShopMarker,
ClientOnly,
Loading
},
props: {
center: {
type: Array,
required: true
},
zoom: {
type: Number,
required: true
},
tilesUrl: {
type: String,
// cf. https://sosm.ch/projects/tile-service/
default: 'https://tile.osm.ch/switzerland/{z}/{x}/{y}.png'
}
},
data: () => ({
shop: undefined,
spinnerColor: '#e78000ff'
}),
computed: {
loadingMapData () {
return this.$apollo.queries.shops.loading
},
options () {
return {
gestureHandling: true,
gestureHandlingOptions: {
text: {
touch: this.$i18n.t('gestureHandling.touch'),
scroll: this.$i18n.t('gestureHandling.scroll'),
scrollMac: this.$i18n.t('gestureHandling.scrollMac')
},
duration: 2000
},
zoomControl: false
}
}
},
methods: {
displayDescription (id) {
this.shop = this.shops.find(item => item.id === id)
},
clearDescription () {
this.shop = undefined
}
}
}
</script>
<style src="~/assets/css/tailwind.css"></style>
<style src="vue-loading-overlay/dist/vue-loading.css"></style>
<style src="leaflet/dist/leaflet.css"></style>
<style src="leaflet-gesture-handling/dist/leaflet-gesture-handling.css"></style>
<style>
/* .leaflet-tile-pane {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
} */
</style>
and here's my nuxt config:
import i18n from './i18n'
const path = require('path')
const pkg = require('./package')
module.exports = {
mode: 'universal',
env: {
GRAPHQL_API: process.env.GRAPHQL_API || 'http://localhost:8080/v1/graphql/'
},
/*
** Headers of the page
*/
head: {
title: pkg.name,
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{ src: '~plugins/errorHandling.js' },
{ src: '~plugins/leaflet.js', mode: 'client' }
],
buildModules: [
'@nuxtjs/tailwindcss'
],
/*
** Nuxt.js modules
*/
modules: ['@nuxtjs/apollo', 'nuxt-purgecss', ['nuxt-i18n', i18n]],
purgeCSS: {
paths: [
'i18n/**/*.js'
]
},
// Give apollo module options
apollo: {
tokenExpires: 10, // optional, default: 7 (days)
includeNodeModules: true, // optional, default: false (this includes graphql-tag for node_modules folder)
authenticationType: 'Basic', // optional, default: 'Bearer'
// optional
// errorHandler (error) {
// console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message)
// },
// required
clientConfigs: {
default: '~/apollo/clientConfig.js'
}
},
/*
** Build configuration
*/
build: {
extractCSS: true,
postcss: {
// Add plugin names as key and arguments as value
// Install them before as dependencies with npm or yarn
plugins: {
// Disable a plugin by passing false as value
// 'postcss-url': false,
// 'postcss-nested': {},
// 'postcss-responsive-type': {},
// 'postcss-hexrgba': {}
},
preset: {
// Change the postcss-preset-env settings
autoprefixer: {
grid: true
}
}
},
/*
** You can extend webpack config here
*/
extend (config, ctx) {
config.resolve.alias['~graphql'] = path.resolve(__dirname, '../../shared/graphql/')
}
}
}
and here's my leaflet.js
plugin:
import Vue from 'vue'
import { LMap, LMarker, LTileLayer } from 'vue2-leaflet'
// eslint-disable-next-line no-unused-vars
import { GestureHandling } from 'leaflet-gesture-handling'
import { Icon } from 'leaflet'
delete Icon.Default.prototype._getIconUrl
Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
})
Vue.component('l-map', LMap)
Vue.component('l-tile-layer', LTileLayer)
Vue.component('l-marker', LMarker)
I'm not using your plugin directly. The bug occurs also without using nuxt-leaflet
. I guess it's misuse of the nuxt
framework. Does anyone have a clue how to make it working?
I'm using:
leaflet@1.6.0
nuxt@2.11.0
vue-client-only@2.0.0
I've tried to
yarn add vue-no-ssr
and use the following map component:
<template>
<div>
<div id="map-wrap" style="height: 100vh; width: 100%;">
<no-ssr>
<l-map :zoom="13" :center="[47.413220, -1.219482]">
<l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png" />
<l-marker :lat-lng="[47.413220, -1.219482]" />
</l-map>
</no-ssr>
</div>
</div>
</template>
Doesn't work either.
If I compile my app as an SPA and don't include
<style src="leaflet/dist/leaflet.css"></style>
in the vue component file, then I get the same issue. It's like the css is not loaded in the static mode if I include the css in the component. If I clone your example and generate the html from it, I see the leaflet css in the generated index file. I don't see that in the html of my project. What can I be missing?
Removing
build.extractCSS: true
from nuxt.config.js
works, but then I can't use webpack configuration.
Sorry I meant wrap it "client-only" tags around the map.
<client-only>
</client-only>
Glad you got it fixed. Please post your fix if it's to any interest for others. Thanks alot!
So in my case it was a misuse of the purgeCSS. I replaced
purgeCSS: {
paths: [
'i18n/**/*.js'
]
},
with
purgeCSS: {
paths: [
'i18n/**/*.js'
],
whitelistPatterns: [/leaflet/, /marker/]
},
in nuxt.config.js
.
@zadigus amazing! so happy you figured this out!
Maybe this could be added to the docs?