问题
Is it possible to use Leaflet with angular/universal? How can I avoid to build Leaflet within server?
After npm run build:prod
dist folder is generated. But when I run node server.js
I get following error:
var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer; Window is not defined.
回答1:
I solved this by mocking window
, navigator
and document
with Mock Browser
Just install the mock browser pacakge
npm i mock-browser
And add the following code to your server.ts
:
const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();
global['window'] = mock.getWindow();
global['document'] = mock.getDocument();
global['navigator'] = mock.getNavigator();
回答2:
After hours of searching I found a solution. You need to use Leaflet with custom service.
leaflet.service.ts
import { Injectable, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Injectable()
export class LeafletService {
public L = null;
constructor(@Inject(PLATFORM_ID) private platformId: Object) {
if (isPlatformBrowser(platformId)) {
this.L = require('leaflet');
}
}
}
map.component.ts
constructor (
private leafletService: LeafletService
) {}
ngAfterViewInit() {
...
this.leafletService.L.map('map').setView([51.505, -0.09], 13);
...
}
There is also an example on GitHub
回答3:
As per the error you are getting you should need to add the platform browser check if you are rendering your application from server, because keywords like window, document etc are not available on server. so add checks like this -
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
export class XYZ implements OnInit{
constructor(@Inject(PLATFORM_ID) private platform: any) { }
ngOnInit() {
if (isPlatformBrowser(this.platform)) {
// use window, document keywords here
}
}
}
来源:https://stackoverflow.com/questions/58080301/how-to-use-angular-universal-with-leaflet