Andy Callaghan
Full stack Ruby dev, from London/York UK
@andycallaghan
andycallaghan.com
@andycallaghan
andycallaghan.com
festicket.com/festivals
<head>
<script
type="text/javascript"
src=”//maps.googleapis.com/maps/api/js?key=KEY"></script>
</head>
<div id=”map”></div>
<script>
var map = new google.maps.Map(document.getElementById(‘map’), {
...
})
window.google.maps.GeolocationService.geocode("10 Downing Street, London")
</script>
On the page, not in our app's webpack
window.google.maps only available after DCL 🤨
Who can see the problems here?
JS loaded synchronously, first class citizen
<script
src=”//maps.googleapis.com/maps/api/js?key=KEY&callback=initMap"
defer async>
</script>
<div id=”map”></div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById(‘map’), {
...
})
window.google.maps.GeolocationService.geocode("10 Downing Street, London")
}
</script>
<script src=”//maps.googleapis.com/maps/api/js?key=KEY&callback=initMap"
async defer>
</script>
This ties our code to GMaps running initMap callback
JS load no longer in a predictable order
initMap is the entry point to our whole app 🙃
window.google.maps is not available at first
Real Airbrake.io client-side error
Our application's code relies on Google's JS forever
Your code relies on window.google
Spaghetti
Modern apps have lots of components
GMaps becomes THE app on the page, not a component
Other components written for it
yourgolftravel.com
const gmap = async (e) => {
return new Promise(async fulfilled => {
e.style.height = e.style.width = e.getAttribute('size')
let latlng = e.getAttribute('latlng').split(',')
await load('https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&v=3')
let map = new google.maps.Map(e, {
center: new self.google.maps.LatLng(latlng[0], latlng[1]),
zoom: 14
});
fulfilled(map)
})
}
document.addEventListener("DOMContentLoaded", function(event) {
let controls = document.querySelectorAll('div[control=gmap]')
Promise.all(
controls.map(control => {
gmap(control)
})
)
})
<div control='gmap' size='200' latlng='53.9623241,-1.1169397'></div>
const gmap = async (e) => {
return new Promise(async fulfilled => {
e.style.height = e.style.width = e.getAttribute('size')
let latlng = e.getAttribute('latlng').split(',')
await load('https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&v=3')
let map = new google.maps.Map(e, {
center: new self.google.maps.LatLng(latlng[0], latlng[1]),
zoom: 14
});
fulfilled(map)
})
}
document.addEventListener("DOMContentLoaded", function(event) {
let controls = document.querySelectorAll('div[control=gmap]')
Promise.all(
controls.map(control => {
gmap(control)
})
)
})
<div control='gmap' size='200' latlng='53.9623241,-1.1169397'></div>
Async loading, only once
google.maps encapsulated inside a function
Control when it's loaded
Minimal data in the DOM
Plans to standardise this started in 2014
developers.google.com/web/fundamentals/web-components/customelements
w3.org/wiki/WebComponents
import React, { Component } from 'react'
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps"
const MapComponent = withScriptjs(
withGoogleMap((props) =>
<GoogleMap defaultZoom={10} defaultCenter={{ lat: 53.9623241, lng: -1.1169397 }}>
<Marker position={{ lat: 53.9623241, lng: -1.1169397 }} />
</GoogleMap>
))
class App extends Component {
render() {
return (
<divf>
<header>
<h1>React Google Maps</h1>
</header>
<MapComponent
googleMapURL="https://maps.googleapis.com/maps/api/js?v=3"
/>
</div>
);
}
}
import React, { Component } from 'react'
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps"
const MapComponent = withScriptjs(
withGoogleMap((props) =>
<GoogleMap defaultZoom={10} defaultCenter={{ lat: 53.9623241, lng: -1.1169397 }}>
<Marker position={{ lat: 53.9623241, lng: -1.1169397 }} />
</GoogleMap>
))
class App extends Component {
render() {
return (
<div>
<header>
<h1>React Google Maps</h1>
</header>
<MapComponent
googleMapURL="https://maps.googleapis.com/maps/api/js?v=3"
/>
</div>
);
}
}
Compiled script handling markers & async loading
Componentised element
Data out of the DOM
Other interactions with the map become components
@AndyCallaghan
andycallaghan.com
yourgolftravel.com
All code at
github.com/acallaghan/coupling-google-maps
By Andy Callaghan
A technical talk about using the Google Maps JS badly on a website, the technical debt that can be accrued, and a few different modern techniques to use it well. When we rely on Google Maps for it’s API (I.e. geocoding addresses, Places API) it becomes a hard dependency on your JS code that becomes a legacy problem and hard to remove.