visgl / visgl/react-google-maps
[Feat] Implement Static fallback via the Maps Static API
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.9k
- Forks
- 193
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 13
Description
Target Use Case
Minimize the user experience impact of the library by improving paint time and responsiveness metrics.
Proposal
Data from HTTP Archive shows that Google Maps has the longest download times during page rendering when compared to the other most popular third-party libraries on the web:
| Median download time during page rendering for the top 10 most popular third parties (calculated using HTTP Archive and Lighthouse’s wastedMs attribute via the render blocking audit) |
| Query |
This happens because the Maps JavaScript API fetches ~240 kB of JavaScript across multiple scripts. In this library, we can circumvent this by delaying the instantiation of these scripts until the user engages with the map. While waiting for the user’s interaction, we can fetch and display an image via the Maps Static API passing in the same set of required props (center and zoom).
Optimized prototype of react-google-maps that displays an image and defers JS until user interaction) |
| Link |
To implement this feature, the <APIProvider> component of the library can keep track of whether the map has been selected as part of the context information it provides. We can use this to conditionally render either the “real” map versus a static version of it:
// src/components/map/index.tsx
import { StaticMap } from "./static-map";
// ...
return (
<div onClick={() => context.setMapSelected(true)}>
>
{context.mapSelected ? (
// Load normal map
) : (
<StaticMap {...props} /> // Load Static Map if map hasn't been clicked
)}
</div>
);
You can see all the changes in this prototype in this commit. Note that this is just a prototype, and the real implementation would offer some sort of UI that makes it clear that the map needs to be clicked in order to be interacted with.
Performance Tests
Comparing the current version of react-google-maps with the prototype above on the same site shows a significant difference in rendering times:
When the user interacts with the map, the same scripts are still fetched and executed. But by deferring them until they’re needed, the browser's main thread is freed up to handle other tasks while the document continues to load. This will improve both Largest Contentful Paint and Interaction to Next Paint.
The chart and table below present a comparison of these two metrics when applying this optimization to a representative Next.js website: https://news-site-next-static.netlify.app/.
| Largest Contentful Paint | Total Blocking Time* | |
|---|---|---|
| News Site Next | 3.38s | 0.25s |
News Site Next with react-google-maps |
7.12s (+3.74s) | 0.97s (+0.72s) |
News Site Next with react-google-maps (Optimized) |
4.22s (+0.84s) | 0.44s (+0.19s) |
Test conditions: WebPageTest - Emulated 4G Connection, Chrome, Moto G4 (Median Results - 3 Runs)
*Total Blocking Time is used as a lab proxy here for Interaction to Next Paint
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/components/map/index.tsx and the APIProvider context, then compare the prototype in the linked static-facade commit. Implement a StaticMap path using the documented center and zoom props, defer the regular map until user interaction, and provide UI indicating that interaction is required.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend, performance, web-dev
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100