Skip to content

Commit 8347129

Browse files
authored
build: load Google Maps and YouTube APIs on demand in dev app (angular#25162)
Only loads the Google Maps and YouTube APIs when they are necessary in the dev app. This will make the app load quicker and reduce the amount of logs in the console.
1 parent 323359c commit 8347129

File tree

4 files changed

+59
-22
lines changed

4 files changed

+59
-22
lines changed

src/dev-app/google-map/google-map-demo.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<div class="demo-google-map">
1+
<div *ngIf="!hasLoaded">Loading Google Maps API...</div>
2+
<div class="demo-google-map" *ngIf="hasLoaded">
23
<google-map height="400px"
34
width="750px"
45
[center]="center"

src/dev-app/google-map/google-map-demo.ts

+44-7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const CIRCLE_CENTER: google.maps.LatLngLiteral = {
4444
};
4545
const CIRCLE_RADIUS = 500000;
4646

47+
let apiLoadingPromise: Promise<unknown> | null = null;
48+
4749
/** Demo Component for @angular/google-maps/map */
4850
@Component({
4951
selector: 'google-map-demo',
@@ -96,6 +98,7 @@ export class GoogleMapDemo {
9698
};
9799

98100
isGroundOverlayDisplayed = false;
101+
hasLoaded: boolean;
99102
groundOverlayImages = [
100103
{
101104
title: 'Red logo',
@@ -116,19 +119,16 @@ export class GoogleMapDemo {
116119
isBicyclingLayerDisplayed = false;
117120

118121
mapTypeId: google.maps.MapTypeId;
119-
mapTypeIds = [
120-
google.maps.MapTypeId.HYBRID,
121-
google.maps.MapTypeId.ROADMAP,
122-
google.maps.MapTypeId.SATELLITE,
123-
google.maps.MapTypeId.TERRAIN,
124-
];
122+
mapTypeIds = ['hybrid', 'roadmap', 'sattelite', 'terrain'] as google.maps.MapTypeId[];
125123

126124
markerClustererImagePath =
127125
'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m';
128126

129127
directionsResult?: google.maps.DirectionsResult;
130128

131-
constructor(private readonly _mapDirectionsService: MapDirectionsService) {}
129+
constructor(private readonly _mapDirectionsService: MapDirectionsService) {
130+
this._loadApi();
131+
}
132132

133133
authFailure() {
134134
console.log('Auth failure event emitted');
@@ -257,4 +257,41 @@ export class GoogleMapDemo {
257257

258258
return result;
259259
}
260+
261+
private _loadApi() {
262+
this.hasLoaded = !!window.google?.maps;
263+
264+
if (this.hasLoaded) {
265+
return;
266+
}
267+
268+
if (!apiLoadingPromise) {
269+
// Key can be set through the `GOOGLE_MAPS_KEY` environment variable.
270+
const apiKey: string | undefined = (window as any).GOOGLE_MAPS_KEY;
271+
272+
apiLoadingPromise = Promise.all([
273+
this._loadScript(
274+
`https://maps.googleapis.com/maps/api/js?libraries=visualization${
275+
apiKey ? `&key=${apiKey}` : ''
276+
}`,
277+
),
278+
this._loadScript('https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js'),
279+
]);
280+
}
281+
282+
apiLoadingPromise.then(
283+
() => (this.hasLoaded = true),
284+
error => console.error('Failed to load Google Maps API', error),
285+
);
286+
}
287+
288+
private _loadScript(url: string): Promise<unknown> {
289+
return new Promise((resolve, reject) => {
290+
const script = document.createElement('script');
291+
script.src = url;
292+
script.addEventListener('load', resolve);
293+
script.addEventListener('error', reject);
294+
document.body.appendChild(script);
295+
});
296+
}
260297
}

src/dev-app/index.html

-13
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,7 @@
1717
</head>
1818
<body>
1919
<dev-app>Loading...</dev-app>
20-
2120
<script src="zone.js/dist/zone.js"></script>
22-
<script src="https://www.youtube.com/iframe_api"></script>
23-
<script src="https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js"></script>
24-
<script>
25-
(function loadGoogleMaps() {
26-
// Key can be set through the `GOOGLE_MAPS_KEY` environment variable.
27-
const key = window.GOOGLE_MAPS_KEY;
28-
const script = document.createElement('script');
29-
script.src = 'https://maps.googleapis.com/maps/api/js?libraries=visualization' +
30-
(key ? '&key=' + key : '');
31-
document.body.appendChild(script);
32-
})();
33-
</script>
3421
<script src="bundles/dev-app/main.js" type="module"></script>
3522
</body>
3623
</html>

src/dev-app/youtube-player/youtube-player-demo.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ export class YouTubePlayerDemo implements AfterViewInit, OnDestroy {
5353
videoWidth: number | undefined;
5454
videoHeight: number | undefined;
5555

56-
constructor(private _changeDetectorRef: ChangeDetectorRef) {}
56+
constructor(private _changeDetectorRef: ChangeDetectorRef) {
57+
this._loadApi();
58+
}
5759

5860
ngAfterViewInit(): void {
5961
this.onResize();
@@ -70,4 +72,14 @@ export class YouTubePlayerDemo implements AfterViewInit, OnDestroy {
7072
ngOnDestroy(): void {
7173
window.removeEventListener('resize', this.onResize);
7274
}
75+
76+
private _loadApi() {
77+
if (!window.YT) {
78+
// We don't need to wait for the API to load since the
79+
// component is set up to wait for it automatically.
80+
const script = document.createElement('script');
81+
script.src = 'https://www.youtube.com/iframe_api';
82+
document.body.appendChild(script);
83+
}
84+
}
7385
}

0 commit comments

Comments
 (0)