Solución de problemas
Busca el síntoma que ves, aplica la solución y sigue el enlace para ver los detalles completos. Las entradas describen la versión 1.6.1.
Carga y registro
El elemento queda vacío
Revisa estos puntos en orden. El primero que falla suele ser la causa.
| Qué ves | Causa probable | Solución |
|---|---|---|
customElements.get('mapvx-website') devuelve undefined en la consola | main.js no se cargó o no se pudo analizar | Cárgalo con type="module" desde una URL que devuelva JavaScript y permite su host en el script-src de tu CSP. Consulta Unexpected token 'export' y Unexpected token '<'. |
| El elemento está definido pero no tiene ancho | <mapvx-website> es un elemento inline por defecto y puede colapsar, por ejemplo dentro de una fila flex | Agrega mapvx-website { display: block; width: 100%; }. Consulta Tamaño. |
| Aparecen el cuadro de búsqueda y el selector Grid View / Map View, pero no hay tarjetas y el mapa está en blanco | Ninguna API key llegó al componente, o fallan las solicitudes a la API de MapVX | Define api-key en kebab-case (un atributo apiKey se ignora). En la pestaña Network, busca solicitudes a public-api.mapvx.com: si no hay ninguna, el componente no tiene API key. Consulta API key. |
| El componente se muestra sin colores, y el mapa y los marcadores se ven rotos | styles.css no está cargado | Agrega la hoja de estilos de la misma versión que main.js. |
| Aparecen las tarjetas, pero el área del mapa sigue vacía | Falta un requisito del mapa | Consulta El mapa queda en blanco. |
Una integración mínima que pasa todas estas revisiones:
<link rel="stylesheet" href="https://unpkg.com/@mapvx/web-components-ssr@1.6.1/dist/browser/styles.css" />
<script type="module" src="https://unpkg.com/@mapvx/web-components-ssr@1.6.1/dist/browser/main.js"></script>
<style>
mapvx-website {
display: block;
width: 100%;
}
</style>
<mapvx-website api-key="YOUR_API_KEY" institution-id="YOUR_INSTITUTION_ID"></mapvx-website>Fija la versión exacta que probaste. El bundle de producción no informa los problemas de configuración en la consola: consulta Depuración para saber qué sí muestra la consola.
SyntaxError: Unexpected token 'export'
Causa: main.js se carga como script clásico. Desde la 1.3.0 es un módulo ES, y un script
clásico no puede contener la instrucción export del final del archivo, así que el navegador
rechaza el archivo completo y no se ejecuta nada. El elemento nunca se registra y queda vacío, sin
ningún otro error. El mensaje es el de Chromium; otros navegadores lo redactan de otra manera.
Solución: agrega type="module" a la etiqueta script. Los scripts de módulo se difieren
automáticamente, así que defer ya no hace falta. Lo mismo vale para cualquier herramienta que
inserte main.js como script clásico.
<!-- Antes -->
<script src="/mapvx-website/1.6.1/main.js" defer></script>
<!-- Después -->
<script type="module" src="/mapvx-website/1.6.1/main.js"></script>Consulta Instalación.
Unexpected token '<' en Angular
Causa: la URL del script no apunta a un archivo que tu servidor sirva, así que el servidor
responde con una página HTML, normalmente el index.html de tu app como página de respaldo. El
navegador intenta entonces ejecutar HTML como JavaScript. Un script clásico falla con
Unexpected token '<'. Un script de módulo falla con un error de tipo MIME: Chromium informa
Failed to load module script e indica que el servidor respondió con el tipo MIME "text/html".
Solución: copia la carpeta dist/browser del paquete a la salida de tu build con una entrada
en el arreglo assets del target de build en angular.json, y apunta las etiquetas a ella:
{
"glob": "**/*",
"input": "node_modules/@mapvx/web-components-ssr/dist/browser",
"output": "mapvx-website/1.6.1"
}<!-- src/index.html, dentro de <head>. Al actualizar, cambia la versión aquí y en angular.json. -->
<link rel="stylesheet" href="mapvx-website/1.6.1/styles.css" />
<script type="module" src="mapvx-website/1.6.1/main.js"></script>Las rutas relativas se resuelven contra tu <base href>. Abre la URL del script en una pestaña
del navegador: debe mostrar JavaScript, no tu app. Consulta Angular.
chunk-*.js devuelve 404, o Failed to fetch dynamically imported module
Causa: main.js carga los archivos chunk-*.js en forma relativa a su propia URL, y cada
chunk importa ./main.js con ese nombre exacto. Los chunks contienen el código del mapa 3D, que
main.js importa solo para mapas 3D. En la 1.6.1 el mapa del componente es 2D, así que una carga
de la página solo pide main.js y styles.css del paquete, y un chunk faltante o de otra versión
pasa inadvertido hasta que algo lo carga. Las importaciones fallan cuando:
main.jsse renombró (por ejemplo, abundle.js). Los chunks piden./main.jsy reciben un error 404. Si elmain.jsoriginal también está ahí, se ejecuta por segunda vez: consultaNotSupportedError.- Los chunks no se copiaron junto a
main.js, o vienen de otra versión. Los nombres de los chunks llevan un hash de contenido, así que una versión que cambia un chunk también le cambia el nombre. - Un
main.jsen caché de una versión anterior pide chunks que ya no existen.main.jsconserva el mismo nombre entre versiones. - Los archivos se sirven desde otro origen sin el encabezado
Access-Control-Allow-Origin. Los navegadores piden los scripts de módulo en modo CORS, así que sin ese encabezado ni siquieramain.jsse carga. unpkg y jsDelivr lo envían. - Un servidor que responde a los archivos inexistentes con una página HTML produce un error de tipo MIME en lugar de un error 404.
El mensaje del título es el de Chromium; otros navegadores lo redactan de otra manera.
Solución: copia la carpeta dist/browser completa, sin cambiar los nombres de archivo, a una
ruta con la versión, y reemplaza la carpeta entera en cada actualización. En un CDN, fija una
versión exacta: jsDelivr sirve @latest directamente y permite que los navegadores lo guarden en
caché hasta 7 días.
// copy-mapvx.mjs: ejecútalo después de npm install
import { cpSync, readFileSync, rmSync } from 'node:fs'
const pkgDir = 'node_modules/@mapvx/web-components-ssr'
const { version } = JSON.parse(readFileSync(`${pkgDir}/package.json`, 'utf8'))
rmSync('public/mapvx-website', { recursive: true, force: true })
// Conserva todos los nombres tal como se publicaron: los chunks importan './main.js'
cpSync(`${pkgDir}/dist/browser`, `public/mapvx-website/${version}`, { recursive: true })Luego carga /mapvx-website/1.6.1/main.js y /mapvx-website/1.6.1/styles.css. Consulta
Alojamiento propio.
NotSupportedError: el nombre mapvx-website ya se usó
Causa: el bundle se evaluó dos veces. El navegador ejecuta un módulo una vez por URL, así que el mismo bundle con dos URLs distintas se ejecuta dos veces:
- el mismo bundle desde dos rutas, por ejemplo una URL de CDN y una copia alojada por ti;
- una etiqueta
<script>más unimporten tu código empaquetado; - una copia renombrada de
main.jsjunto a la original; - dos versiones en la misma página;
- una query string en la URL del script (
main.js?v=2): los chunks importan./main.jssin ella, que es otra URL, así que el bundle se vuelve a ejecutar en cuanto se carga un chunk (en la 1.6.1, solo los mapas 3D cargan chunks).
El primer registro sigue funcionando, pero la segunda copia de todos modos inicia su propia aplicación antes de fallar. El error se escribe en la consola.
Solución: carga el bundle una sola vez, desde una sola URL. Para invalidar cachés, cambia el
directorio (/mapvx-website/1.6.1/main.js) en lugar de agregar una query string. Para encontrar
el duplicado, filtra la pestaña Network por main.js.
ReferenceError: HTMLElement is not defined
Causa: tu código de servidor importa el bundle. El bundle usa APIs del navegador apenas se evalúa, así que lanza un error en Node.
Solución: impórtalo solo en el navegador: con un <script type="module">, con un import()
dinámico dentro de useEffect u onMount, o con un plugin .client de Nuxt. En Next.js, cárgalo
con next/script (Next.js). Consulta
Solo en el cliente.
// React: se ejecuta solo en el navegador, después de la hidratación
useEffect(() => {
import('@mapvx/web-components-ssr')
}, [])React informa un error de hidratación
Causa: con el renderizado en el servidor de React 19, si el bundle activa <mapvx-website> y
renderiza su contenido antes de que React hidrate la página, React informa
Hydration failed because the server rendered HTML didn't match the client y regenera el árbol
en el cliente.
Solución: carga el bundle después de la hidratación. En Next.js, usa el componente <Script>
con su estrategia por defecto, afterInteractive; en otras configuraciones de React, usa un
import() dinámico dentro de useEffect. Consulta Next.js.
Tu framework rechaza <mapvx-website>
- Angular,
'mapvx-website' is not a known element: agregaschemas: [CUSTOM_ELEMENTS_SCHEMA]al componente que usa la etiqueta. - TypeScript con JSX,
Property 'mapvx-website' does not exist on type 'JSX.IntrinsicElements': el paquete no trae tipos para el elemento, así que decláralo tú. Consulta Tipado del elemento. - Vue, advertencia
Failed to resolve component: mapvx-website: definecompilerOptions.isCustomElement. Sin eso, Vue registra los listeners@userActionpara un evento llamadouser-action, así que tampoco se disparan. Consulta Vue.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
@Component({
selector: 'app-directory',
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `<mapvx-website api-key="YOUR_API_KEY" institution-id="YOUR_INSTITUTION_ID"></mapvx-website>`,
})
export class DirectoryComponent {}Datos y atributos
Cada tarjeta de lugar aparece dos veces
Problema conocido de la 1.6.1: combinar initial-data con api-key lista cada lugar dos veces.
Causa: con initial-data, el componente de todos modos pide los lugares a la API y los agrega
a los lugares de initial-data sin quitar los duplicados. Cada cambio posterior de
institution-id o de initial-data, y cada vez que el elemento se vuelve a montar en la misma
sesión de la página, agrega los lugares una vez más. Los marcadores del mapa no se duplican.
Solución temporal: omite initial-data y deja que el componente cargue los datos en el
navegador. initial-data no evita las solicitudes a la API ni agrega el marcado de los lugares al
HTML de tu servidor, así que omitirlo solo significa que las primeras tarjetas aparecen cuando
responde la API. Si lo mantienes, no cambies institution-id ni initial-data después del primer
renderizado. Consulta
Problema conocido: tarjetas de lugares duplicadas.
Una función desapareció al agregar un atributo booleano
Causa: solo el string exacto "true" activa un atributo booleano. Un atributo escrito sin
valor tiene el valor "", que cuenta como false, igual que "1", "TRUE" y "yes".
show-category-filters y show-city-filter son true por defecto, así que escribirlos sin
valor oculta las pestañas de categorías o el filtro de ciudad. Quitar un atributo también cuenta
como false, no como el valor por defecto.
<!-- Oculta el filtro de ciudad: "" cuenta como false -->
<mapvx-website show-city-filter></mapvx-website>
<!-- Lo muestra -->
<mapvx-website show-city-filter="true"></mapvx-website>Solución: escribe siempre "true" o "false", en kebab-case (un atributo showCityFilter
se ignora). En los frameworks:
- React 19 renderiza
default-to-map={true}comodefault-to-map=""(false) y omite{false}(así se aplica el valor por defecto): pasa los strings"true"y"false". - Un binding
[attr.show-city-filter]de Angular con valornullquita el atributo, lo que también cuenta como false. - Como propiedades de JavaScript, los booleanos reales funcionan:
el.showCityFilter = false.
Consulta Atributos booleanos y Quitar atributos.
default-to-map no tiene efecto
Causa: desde la 1.6.0 el componente recuerda la última elección de Grid View / Map View del
visitante en localStorage, con la clave mapvx:active-view, compartida por todas las páginas
de tu origen. Una elección guardada tiene prioridad sobre default-to-map, que solo decide la
primera vista para los visitantes que nunca la cambiaron. Revisa también que el valor sea
exactamente "true".
Solución: mientras pruebas, borra los datos del sitio o elimina la clave. Para que
default-to-map tenga prioridad en cada carga, elimina la clave antes de que se cargue el
bundle. Esto también descarta la elección del visitante.
<script>
try {
localStorage.removeItem('mapvx:active-view')
} catch {}
</script>
<script type="module" src="https://unpkg.com/@mapvx/web-components-ssr@1.6.1/dist/browser/main.js"></script>Consulta Vista recordada.
TypeError al quitar institution-id
Causa: quitar el atributo institution-id deja su valor en null, y el componente llama a
.trim() sobre él. La consola muestra CustomErrorHandler seguido de un TypeError (en
Chromium: Cannot read properties of null (reading 'trim')). Los frameworks suelen quitar un
atributo cuando lo enlazas a null o undefined.
Solución: mantén el atributo y asígnale un string vacío en lugar de quitarlo.
el.setAttribute('institution-id', '') // en lugar de el.removeAttribute('institution-id')<!-- Plantilla de Angular -->
<mapvx-website [attr.institution-id]="institutionId ?? ''"></mapvx-website>Asignar un objeto a la propiedad initialData también lanza un TypeError: pasa un string
JSON, JSON.stringify(data). Consulta Quitar atributos.
No hay pestañas de categorías, o la ciudad es incorrecta
Causa: las pestañas de categorías vienen de la institución cuyo id es exactamente igual a
institution-id. Si el atributo falta o no coincide con ninguna institución disponible para tu
API key, no aparecen pestañas hasta que el visitante elige una ciudad o abre un lugar. Si además
no coincide con ninguna opción de ciudad, la cuadrícula usa la primera ciudad de tu configuración.
Un id con otras mayúsculas no coincide ni con una institución ni con una opción de ciudad. Un id
con espacios al inicio o al final no coincide con ninguna institución, aunque sí selecciona su
ciudad, porque las opciones de ciudad se comparan después de quitar esos espacios. El bundle de
producción no informa nada al respecto.
La barra de pestañas también se oculta cuando show-category-filters no es "true" (consulta
Una función desapareció), o cuando All es la única
categoría que queda.
Solución: usa el id de institución que te entregó MapVX, exactamente como te lo dieron. Consulta Id de institución.
Varios elementos en una página se comportan mal
Causa: los elementos de una página no son independientes. Comparten una aplicación: un router,
un conjunto de datos cargados, un mapa y un SDK, y gana la primera api-key. Síntomas típicos: un
elemento deja de actualizarse cuando otro navega, el mapa salta de un elemento a otro, y al abrir
un lugar la página se desplaza al primer elemento.
Solución: usa un elemento por página. Para mostrar varias instituciones, dale a cada una su
propia página, o cambia institution-id en un solo elemento, que se actualiza en tiempo de
ejecución (sin initial-data: consulta
Cada tarjeta de lugar aparece dos veces).
Eventos y navegación
Los listeners de userAction nunca se disparan
- Usa los nombres exactos en camelCase
userActionycardSelected.useractionyuser-actionnunca se disparan. - Agrega el listener al propio elemento
<mapvx-website>. Los eventos no burbujean, así que los listeners endocumento en un elemento padre nunca los reciben, salvo que escuchen en la fase de captura. - Agrégalo temprano. Los eventos no se vuelven a emitir, así que un listener tardío se pierde los
primeros, como el
show-placede un enlace con?tenant=.addEventListenerfunciona incluso antes de que se defina el elemento. - React 18: las props de eventos no funcionan; usa un ref y
addEventListener. React 19: usaonuserAction(onUserActionno se dispara). - Vue: define
compilerOptions.isCustomElement. Si no, Vue registra los listeners@userActionpara un evento llamadouser-action, que nunca se emite.
const el = document.querySelector('mapvx-website')
// Funciona antes de que se defina el elemento: no hace falta esperar ni sondear
el.addEventListener('userAction', (event) => {
const { type, data } = event.detail
console.log(type, data)
})Consulta Escuchar eventos y Recetas por framework.
El componente vuelve a abrir un lugar una y otra vez
Causa: el componente lee ?search=, ?tenant= y ?destination= de la URL de tu página
cada vez que crea su pantalla de inicio: en la primera carga y cada vez que el visitante vuelve al
inicio desde el perfil de un lugar (el botón Back de la pantalla de ruta lleva primero al perfil
del lugar). Al salir de los resultados de búsqueda se mantiene la misma pantalla de inicio, así
que en ese momento no se vuelven a leer los parámetros. Si un parámetro ?tenant= queda en la
URL, el botón Back del componente vuelve al inicio, y el inicio abre ese lugar otra vez. Lo mismo
pasa con una ruta (?destination=) o una búsqueda (?search=). Los nombres search, tenant,
destination y tab están reservados: si tu página los usa para otra cosa, el componente los
trata como enlaces profundos.
Solución: quita los parámetros de enlace profundo cuando recibas return-to-home. El evento
se emite antes de que el componente navegue al inicio, así que un history.replaceState
síncrono en el listener se aplica a tiempo.
const el = document.querySelector('mapvx-website')
el.addEventListener('userAction', (event) => {
if (event.detail.type !== 'return-to-home') return
const url = new URL(location.href)
for (const name of ['search', 'tenant', 'destination']) url.searchParams.delete(name)
history.replaceState(history.state, '', url)
})Consulta Enlaces profundos y Sincronizar la URL de la página.
El botón Atrás del navegador lleva el componente al inicio
Causa: mientras un perfil de lugar está abierto, el componente trata cada evento popstate
como Back: emite return-to-home y muestra su pantalla de inicio. Eso incluye los botones Atrás
y Adelante del navegador, history.back() y history.go(), la navegación por el historial que
hace tu propio router y la navegación que solo cambia el hash, como un enlace a un ancla
(#section) o un script que asigna location.hash. Las pantallas de búsqueda y de ruta no
escuchan ese evento: ahí el botón Atrás solo cambia la URL de tu página, y el componente se queda
donde está.
Si sincronizas la URL: tu handler de return-to-home también se ejecuta después de un Atrás
del navegador. Un pushState ahí agrega una entrada nueva al historial y borra el historial
hacia adelante, así que usa history.replaceState para return-to-home. Consulta
Botón Atrás del navegador.
La página se desplaza al abrir un lugar
Causa: abrir el perfil de un lugar (desde una tarjeta, un marcador del mapa, un enlace con
?tenant= o el botón Back de la pantalla de ruta) desplaza la página con suavidad hasta el inicio
del primer <mapvx-website> del documento. No se puede desactivar.
Solución: si un encabezado fijo tapa el inicio del componente, agrega un margen de desplazamiento:
mapvx-website {
scroll-margin-top: 80px; /* alto de tu encabezado fijo */
}Mapa, búsqueda y ubicación
El mapa queda en blanco
Las tarjetas pueden funcionar mientras el área del mapa sigue vacía, porque el mapa tiene sus propios requisitos.
| Causa | Cómo confirmarlo | Solución |
|---|---|---|
| No hay API key, o falló la solicitud de la configuración o del estilo del mapa | En la pestaña Network, no hay ninguna solicitud a public-api.mapvx.com, o hay una con estado de error | Define api-key. El mapa se crea solo después de que carga la configuración. |
| El navegador no puede crear un contexto WebGL | Un error en la consola que contiene Failed to initialize WebGL; en Chrome, revisa chrome://gpu | Activa la aceleración por hardware, o prueba con otro navegador o dispositivo. La 1.6.1 usa WebGL2 y, si no está disponible, recurre a WebGL 1. |
| Tu CSP bloquea el worker del mapa | Una violación de CSP de worker-src con una URL blob: | Agrega worker-src blob:. |
| Tu CSP bloquea los datos del mapa | Violaciones de CSP de connect-src (teselas, sprites y glifos de las etiquetas del mapa) | Permite los hosts que se indican en la política con lista de permitidos. |
Falta styles.css | Faltan los colores, y el mapa y los marcadores se ven rotos | Carga styles.css. |
La búsqueda se queda en “Looking for your results…”
Causa: falló una solicitud de búsqueda (error de red, error de la API o un bloqueo de la
CSP). La vista de búsqueda no se recupera: sigue mostrando las tarjetas provisionales de carga, y
escribir no hace nada hasta que el visitante sale de la vista de búsqueda con Back o con la X del
cuadro de búsqueda. La consola muestra un error CustomErrorHandler.
Solución: busca la solicitud fallida en la pestaña Network. Si la bloqueó tu CSP, permite los
hosts de la API de MapVX en connect-src (consulta
Política con lista de permitidos).
El botón de ubicación no hace nada
Causa: el visitante negó el acceso a su ubicación, o la solicitud superó el tiempo de espera
(5 segundos). En ambos casos el botón no hace nada ni muestra ningún mensaje, y la opción
“Use current location” del selector de origen de la ruta se oculta mientras el acceso está
negado. La ubicación además requiere un contexto seguro (HTTPS) y, dentro de un <iframe> de otro
origen, el atributo allow="geolocation". El navegador pide el permiso solo cuando el visitante
hace clic en el botón o elige “Use current location”.
Solución: sirve la página por HTTPS, permite la geolocalización en los iframes, y pide a los visitantes que la negaron que permitan la ubicación en la configuración del sitio de su navegador.
<iframe src="https://www.example.com/directory" allow="geolocation"></iframe>Consulta Permisos del navegador.
Estilos
El CSS de tu página cambia el componente
Causa: el componente no usa Shadow DOM. Se renderiza en el DOM de tu página, así que tus
reglas con selectores de elemento o universales (button, input, img, h1, h3, p,
* { box-sizing: ... }) también se aplican dentro de él. El título del lugar es un <h1> y los
títulos de las tarjetas son <h3>. Los estilos de los elementos propios del componente están
acotados y no salen de él; la excepción son las reglas globales de styles.css (consulta la
entrada siguiente).
Solución: acota tus reglas globales para que excluyan el componente, o limítalas a tus propios contenedores:
/* También se aplica dentro del componente */
button {
border-radius: 999px;
}
/* Excluye todo lo que está dentro de <mapvx-website> */
button:not(mapvx-website *) {
border-radius: 999px;
}Consulta Aislamiento de estilos.
Tu propio mapa de MapLibre perdió sus controles
Causa: styles.css es global. Oculta .maplibregl-control-container en todos los mapas de
MapLibre de la página, lo que también quita los controles de zoom y la atribución de tu propio
mapa. Además da estilo a nombres de clase genéricos (.marker, .current-location-marker y todo
lo que está dentro de .banner-content) y define más de 100 propiedades personalizadas
--definitions-* en :root.
Solución: restaura el contenedor solo para tu mapa, con un selector más específico, y cambia
el nombre de tus propias clases si chocan con .marker o .banner-content:
#store-map .maplibregl-control-container {
display: block;
}Consulta Estilos globales.
Conflictos con los íconos de Font Awesome
Causa: styles.css incluye el CSS base de Font Awesome 7 (.svg-inline--fa, las clases
.fa-* y los keyframes fa-*), y el componente además inyecta ese CSS en tiempo de ejecución en
un <style id="fa-auto-css">. Si tu página usa otra versión de Font Awesome, ambos conjuntos de
reglas usan los mismos nombres de clase, así que el que viene después en la cascada decide el
tamaño, la alineación y la animación de tus íconos y de los del componente.
Solución: el CSS de Font Awesome del componente no se puede desactivar. Carga tu propio CSS
de Font Awesome después de styles.css para que gane tu versión, y luego revisa los íconos del
componente. Usar Font Awesome 7 en tu página evita la mayoría de las diferencias.
Los colores o las fuentes no cambian
--mapvx-secondary-orangey--mapvx-secondary-bluefuncionan solo en:root, porque se resuelven ahí. Definirlas enmapvx-websiteo en un contenedor no tiene efecto.- El componente no carga Open Sans, su fuente por defecto. Cárgala tú, o define
inherit-font-family="true"para usar la fuente de tu página (los tamaños y pesos de la fuente siguen siendo los del componente). - Muchos botones del componente, como las tarjetas de lugares, los botones Back y los controles
de la ruta, muestran la fuente por defecto que el navegador da a los botones, con o sin
inherit-font-family. Agregamapvx-website button { font-family: inherit; }para que sigan la fuente del componente, y la de tu página cuando definesinherit-font-family="true". Consulta Fuentes.
:root {
--mapvx-secondary-orange: #b41500;
--mapvx-secondary-blue: #053a96;
}
mapvx-website button {
font-family: inherit;
}Consulta Variables CSS y Fuentes.
Seguridad e idioma
Violaciones de CSP en la consola
| Directiva de la violación | Qué bloquea | Qué permitir |
|---|---|---|
script-src | main.js, y el cargador de Google Analytics desde www.googletagmanager.com | El host que sirve main.js, y https://www.googletagmanager.com |
style-src o style-src-elem | Las etiquetas <style> que el componente inyecta en <head> | 'unsafe-inline', o un nonce mediante el atributo ngCspNonce |
style-src-attr | Los atributos style en línea de algunos íconos de Font Awesome, del marcador de ubicación actual y del texto de Deals + Events | 'unsafe-inline' para style-src-attr (los nonces no se aplican a atributos) |
worker-src | El worker del mapa, que se inicia desde una URL blob: | blob: |
connect-src | La API de MapVX, las teselas, los sprites y los glifos de las etiquetas del mapa, los reportes de errores y la analítica | Los hosts de la política con lista de permitidos |
img-src | Las imágenes de los lugares, que vienen de los hosts de tu contenido, y las imágenes en línea | https:, data: y blob: |
Bloquear Google Analytics o los reportes de errores que se envían a https://sentry.mapvx.app
no rompe el componente, pero el navegador registra una violación de CSP por cada solicitud
bloqueada.
Para una política basada en nonces, pon ngCspNonce en el elemento dentro del HTML que sirves,
antes de que se ejecute main.js. El cargador de Google Analytics se agrega sin nonce, así que
agrega también 'strict-dynamic' o permite su host.
<mapvx-website
ngCspNonce="NONCE_VALUE"
api-key="YOUR_API_KEY"
institution-id="YOUR_INSTITUTION_ID"
></mapvx-website>
<script type="module" nonce="NONCE_VALUE" src="/mapvx-website/1.6.1/main.js"></script>Consulta Content Security Policy, Nonce para los estilos inyectados y
'strict-dynamic'.
La interfaz solo está en inglés
Los textos de la interfaz están fijos en inglés. No hay un atributo de idioma, y el componente no
lee <html lang>. Los datos que carga el SDK incluido (como los lugares, las categorías y las
instrucciones de la ruta) también se piden en inglés. Las etiquetas del mapa no: el mapa las
muestra en el idioma por defecto definido en tu configuración de MapVX. Los formatos son de
Estados Unidos: horas en formato de 12 horas, distancias en pies y teléfonos como
XXX.XXX.XXXX. Los nombres de las pestañas de categorías vienen de tu contenido en MapVX tal
como se escribieron. No hay ninguna opción en el elemento para cambiar el idioma.
Depuración
El bundle de producción es silencioso. Sus mensajes de diagnóstico solo se imprimen en los builds de desarrollo, y no hay ninguna opción para activar la depuración. El componente no imprime nada ante estos problemas, aunque el navegador puede registrar igualmente las solicitudes de red fallidas:
- JSON inválido en
initial-data; - un
institution-idque no coincide con ninguna institución ni ciudad; - solicitudes fallidas a la API para lugares, configuración o instituciones;
- solicitudes de ruta fallidas.
Lo que sí puede mostrar la consola:
CustomErrorHandlerseguido de un error: un error no capturado dentro del componente.requestLocationPermission grantedodenied,startWatching,hasBearingPermission: mensajes informativos de la función de ubicación.- Mensajes del SDK de mapas incluido, como
clickedPlacecuando se hace clic en un lugar de un mapa de interiores, y errores del mapa comoFailed to initialize WebGL. - Mensajes en español como
Error en navegación inicial(un error interno de navegación) yContexto WebGL perdido(el navegador perdió el contexto WebGL del mapa). - Violaciones de CSP que informa el navegador.
Revisiones en la consola:
// ¿Está registrado el elemento? undefined significa que main.js no se ejecutó
customElements.get('mapvx-website')
// ¿Qué recibió el componente? Las propiedades devuelven los valores ya interpretados
const el = document.querySelector('mapvx-website')
console.log(el.apiKey, el.institutionId, el.showCityFilter, el.defaultToMap, el.rowsPerPage)
// ¿Qué vista se recuerda para este origen?
localStorage.getItem('mapvx:active-view')Revisiones en la pestaña Network: filtra por mapvx. Los lugares, la configuración, las
instituciones, la búsqueda y el estilo del mapa se cargan desde public-api.mapvx.com, y las
rutas desde api.mapvx.com. Las teselas, los sprites y los glifos de las etiquetas del mapa
vienen de los hosts que indica el estilo del mapa, como tiles.mapvx.com y api.maptiler.com. Si
no hay ninguna solicitud a MapVX, el componente no tiene API key.
Los stack traces apuntan a código minificado en main.js: los source maps no se publican. El SDK
incluido envía sus propios reportes de errores a MapVX; consulta
Reporte de errores.
Cuando informes un problema a MapVX, incluye la versión exacta del paquete, el navegador, la salida de la consola y las solicitudes que fallan.