Angular-google-maps: Os clusters estão interrompendo o aplicativo universal

Criado em 22 nov. 2017  ·  30Comentários  ·  Fonte: SebastianM/angular-google-maps

Descrição do problema

Apenas importar o módulo de cluster está quebrando o aplicativo.

Etapas para reproduzir e uma demonstração mínima do problema

Eu tenho um mapa onde todos os seus marcadores estão sob um cluster. O mapa é agrupado em uma condicional para que seja renderizado apenas no cliente (não no servidor) porque há problemas conhecidos. No entanto, ele ainda interrompe a renderização do lado do servidor porque tenta acessar window em algum ponto. Isso provavelmente acontece durante a inicialização do módulo, uma vez que o próprio componente nunca foi instanciado.

Comportamento atual

Os aplicativos que usam cluster não podem ser usados ​​em um aplicativo do lado do servidor.

Comportamento esperado / desejado

Os aplicativos não devem quebrar.

versão angular e angular-google-maps

  • @angular/* em 5.0.0
  • @agm/core em 1.0.0-beta.2

Outra informação

Estou procurando um caixa eletrônico de solução alternativa, mas, claro, seria bom se os usuários que possuem um aplicativo Universal não precisassem fazer nada. Devemos pelo menos envolver todo o código com isPlatformBrowser e apenas listar isso como uma advertência por enquanto, até descobrirmos como renderizar mapas no servidor, se for possível.

stale

Comentários muito úteis

Eu fiz um fork do projeto js-marker-clusterer e fiz a correção. Impede a inicialização MarkerClusterer quando a janela não está definida (na renderização do lado do servidor). Portanto, o clusterer de marcadores funciona corretamente em ambos os casos agora.

Está publicado em npm. https://www.npmjs.com/package/js-marker-clusterer-universal

js-marker-clusterer dependência js-marker-clusterer-universal para ter efeito.

Todos 30 comentários

@lazarljubenovic sim, embrulhar seria uma boa solução por enquanto.
cc @jigfox

Eu vou olhar para isso

@lazarljubenovic Não tenho nenhuma experiência com aplicativos universais e não tenho certeza de como usar isPlatformBrowser corretamente. Você poderia me dar algumas dicas?

@jigfox Claro! Você pode injetar o token PLATFORM_ID em um componente, assim:

constructor(@Inject(PLATFORM_ID) private platformId: any) {
}

Em seguida, você pode usar funções angulares como isPlatformBrowser ou isPlatformServer para executar condicionalmente certas partes do código apenas em certas plataformas.

constructor(@Inject(PLATFORM_ID) private platformId: any) {
  if (isPlatformBrowser(this.platformId)) {
    console.log('This code runs only in browser')
  }
}

Não tenho certeza de onde colocar isso, a chamada para window está no código fornecido por js-marker-clusterer:

markerclusterer.js # L698 e markerclusterer.js # L1270 então cluster-manager.ts # L3 deve ser encapsulado ?

Talvez seja necessário desabilitar todo o plugin de cluster em plataformas não do navegador? Mas talvez um markerclusterer.js de reescrita pudesse ajudar, porque ele poderia ser reescrito sem uma referência de window

Ah, é um código de biblioteca de terceiros. Caramba. Eu me pergunto se apenas dizer algo assim ajudaria:

const oldWindow = window || {}
window = {
  setTimeout: oldWindow.setTimeout
}
import 'js-marker-clusterer'
window = oldWindow

Mas eu acho que o servidor irá quebrar apenas por encontrar window enquanto executa o código, uma vez que a variável não foi instanciada, então isso provavelmente irá quebrar também, mesmo que seja uma boa ideia.

Podemos fazer import não no início do arquivo, mas dentro de um componente? O que isso faria?

A propósito, está escrito no repositório do Google Maps:

Observação: este repositório não é mantido atualmente e é mantido apenas para fins históricos.

Então, que tal apenas fazermos isso por conta própria? Como é um repositório histórico, ele nunca mudará, o que significa que não há problema em usar nossa própria versão ajustada, que não usa window alguma?

Ah, e com relação a isso:

Mas eu acho que o servidor vai quebrar apenas por encontrar a janela enquanto executa o código, uma vez que a variável não foi instanciada, então isso provavelmente vai quebrar também, mesmo que seja uma boa ideia.

Parece muito básico, mas só aprendi há alguns dias:

Se você tentar fazer if (window == null) ou similar e window não existir como uma variável em nenhum escopo visitado, o código será interrompido com ReferenceError . No entanto, se você fizer if (typeof window == 'undefined' ), funcionará perfeitamente bem e dará os resultados esperados, mesmo que window nunca tenha sido declarado (que é o nosso problema no servidor).

Acho que poderia tentar brincar e criar nossa própria versão do repositório Cluster e ver o que pode ser feito usando isso.

Tentei consertar isso usando a seguinte abordagem:

http://ideasintosoftware.com/typescript-conditional-imports/

Mas não tive sorte, pois o compilador AOT vai começar a reclamar que a diretiva não pode mais ser encontrada.

Sim, o compilador AOT analisa estaticamente o código e, portanto, as importações dinâmicas
com certeza soa como algo que não é possível fazer no Angular.

Você já teve tempo de tentar bifurcar o repositório e apenas remover o acesso a
window ? Parece que ele é usado apenas em alguns lugares que podem facilmente
ser evitado.

Em 27 de dezembro de 2017 18:06, "cmddavid" [email protected] escreveu:

Tentei consertar isso usando a seguinte abordagem:

http://ideasintosoftware.com/typescript-conditional-imports/

Mas não tive sorte, pois o compilador AOT vai começar a reclamar que a diretiva pode
não pode mais ser encontrado.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/SebastianM/angular-google-maps/issues/1241#issuecomment-354144018 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AHTnkXZ85QbMrFT7timh9MPWDeL5piYiks5tEnkmgaJpZM4QmwTi
.

Ainda não, posso tentar ainda esta semana. Não sou fã de alterar o repositório de origem, embora ele não esteja sendo mantido neste momento, pode ser mais tarde. Mas acho que não temos outra opção. Gosto da sugestão de remover completamente as referências da janela, se isso fosse possível, seria ótimo.

Bem, já se passaram dois anos desde a última atualização, então é por isso que eu acho
bifurcação neste caso particular, pelo menos como uma solução temporária,
não seria tão ruim.

Na quinta-feira, 28 de dezembro de 2017 à 1h04, cmddavid [email protected] escreveu:

Ainda não, posso tentar ainda esta semana. Não sou fã de mudar o
no entanto, o repositório de origem, embora não esteja sendo mantido neste momento,
pode ser mais tarde. Mas acho que não temos outra opção. eu gosto de
sugestão de remover completamente as referências da janela, se isso for
possível, isso seria ótimo.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/SebastianM/angular-google-maps/issues/1241#issuecomment-354198599 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AHTnkfZdUcmrInBzlNL41wJ6znRzWVCoks5tEtsHgaJpZM4QmwTi
.

Eu fiz um fork do projeto js-marker-clusterer e fiz a correção. Impede a inicialização MarkerClusterer quando a janela não está definida (na renderização do lado do servidor). Portanto, o clusterer de marcadores funciona corretamente em ambos os casos agora.

Está publicado em npm. https://www.npmjs.com/package/js-marker-clusterer-universal

js-marker-clusterer dependência js-marker-clusterer-universal para ter efeito.

@mbrezovsky bom trabalho, está funcionando bem para mim. Eu recebi um erro relacionado a @agm/js-marker-clusterer usando importações, algo que ainda não é permitido no lado Node.js / Firebase, então eu tive que converter o código para ES2015 usando Anthony Nahas sua solução proposta aqui: https: //github.com/SebastianM/angular-google-maps/issues/1052#issuecomment -331150772

Alguma atualização para esse problema?

@AoschkA Ainda estou usando a solução alternativa mencionada em meu comentário anterior. Você pode encontrar meu exemplo aqui: https://github.com/cmddavid/js-marker-clusterer.git

@cmddavid Seu readme explica apenas como instalar agm / js-marker-clusterer. Como integrar isso em nossos próprios projetos?

@AoschkA , o repo é apenas a saída compilada, eu não fiz nenhuma instrução, você pode adicioná-lo ao seu package.json assim:

"@agm/js-marker-clusterer": "git+https://github.com/cmddavid/js-marker-clusterer.git"

Ao instalá-lo, você terá o js-marker-clusterer sem janela de erros indefinidos e compilado para ES2015 para que seja compatível com serviços como o Firebase.

Thx que funciona. Seria bom se isso pudesse ser implementado no AGM. Mas agradeço a solução @cmddavid !

@cmddavid Fiz como você disse, mas há um erro ERROR em ./node_modules/@agm/js-marker-clusterer/services/managers/cluster-manager.js
Módulo não encontrado: Erro: Não é possível resolver 'js-marker-clusterer-universal' em '. \ Node_modules \ @ agmjs-marker-clusterer \ services \agers'

@maksimbykov você pode confirmar que js-marker-clusterer-universal está na sua pasta node_modules? talvez não tenha sido totalmente instalado, apenas no caso de você poder executar npm i --save js-marker-clusterer-universal . Além disso, algo estranho parece estar acontecendo com os caminhos dos arquivos ali. O primeiro tem uma barra dupla // e o segundo não contém uma barra invertida \ entre node_modules e @agm .

Também vale a pena mencionar que não verifiquei se a embalagem ainda funciona com o angular 6.

@cmddavid muito obrigado! provavelmente ontem eu estava cansado e desatento

Este problema foi marcado automaticamente como obsoleto porque não teve atividades recentes. Ele será fechado se nenhuma outra atividade ocorrer. Obrigado por suas contribuições.

"@ agm / js-marker-clusterer": "git + https://github.com/cmddavid/js-marker-clusterer.git " desculpe, mas não funciona (não instale nada)

Eu fiz um fork do projeto js-marker-clusterer e fiz a correção. Impede a inicialização MarkerClusterer quando a janela não está definida (na renderização do lado do servidor). Portanto, o clusterer de marcadores funciona corretamente em ambos os casos agora.

Está publicado em npm. https://www.npmjs.com/package/js-marker-clusterer-universal

js-marker-clusterer dependência js-marker-clusterer-universal para ter efeito.

Muito obrigado cara, você acabou de me salvar ... parabéns :)

Ainda tenho esse problema, por que ele está marcado como fechado ??

Você literalmente rebateu a explicação sobre o motivo do encerramento. Você viu porque foi fechado.

Você literalmente rebateu a explicação sobre o motivo do encerramento. Você viu porque foi fechado.

então agora podemos reabri-lo: dançarino:

afinal não é mais simples importar js-marker-clusterer dentro da biblioteca e criar um módulo exportável?

eu fiz isso no meu:

https://github.com/alexnoise79/js-marker-clusterer (consulte src / markerclusterer.js)

e então em:
node_modules/@agm/js-marker-clusterer/fesm2015/agm-js-marker-clusterer.js

substituí declare Markerclusterer por:

import * como MarkerClusterer de 'js-marker-clusterer';

funciona e compila ssr 100%

Minha solução se baseia no comentário de @mbrezovsky acima - então

"install:clusterer-universal": "npm i js-marker-clusterer-universal && rm -rf node_modules/js-marker-clusterer && mv node_modules/js-marker-clusterer-universal node_modules/js-marker-clusterer",
"postbuild": "npm run install:clusterer-universal"

e depois de tudo será instalado e substituído.
E o SSR funciona! :)

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

Subhojit1992 picture Subhojit1992  ·  3Comentários

supran2811 picture supran2811  ·  4Comentários

marcelinobadin picture marcelinobadin  ·  3Comentários

nthonymiller picture nthonymiller  ·  4Comentários

gnujeremie picture gnujeremie  ·  3Comentários