Wrapper for the loading of Google Maps JavaScript API script in the browser
npx @tessl/cli install tessl/npm-googlemaps--js-api-loader@1.16.0The Google Maps JavaScript API Loader provides a modern TypeScript/JavaScript wrapper for dynamically loading the Google Maps JavaScript API script in web browsers. It offers Promise-based loading with support for ES6 modules, TypeScript definitions, and various loading strategies including specific library imports and callback-based loading.
npm install @googlemaps/js-api-loaderimport { Loader, LoaderOptions, LoaderStatus, Library, Libraries, DEFAULT_ID } from '@googlemaps/js-api-loader';For CommonJS:
const { Loader, LoaderOptions, LoaderStatus, Library, Libraries, DEFAULT_ID } = require('@googlemaps/js-api-loader');For UMD (browser script tag):
<script src="https://unpkg.com/@googlemaps/js-api-loader@1.x/dist/index.min.js"></script>
<script>
const { Loader } = google.maps.plugins.loader;
</script>import { Loader } from '@googlemaps/js-api-loader';
const loader = new Loader({
apiKey: "YOUR_API_KEY",
version: "weekly",
libraries: ["places", "geometry"]
});
// Modern approach (recommended)
loader.importLibrary('maps').then(({Map}) => {
const map = new Map(document.getElementById("map"), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8
});
});
// Legacy approach (deprecated)
loader.load().then((google) => {
const map = new google.maps.Map(document.getElementById("map"), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8
});
});The Google Maps JavaScript API Loader is built around these key components:
Main class for loading Google Maps JavaScript API dynamically with Promise support. The constructor sets default values for optional parameters: id defaults to DEFAULT_ID, libraries defaults to [], retries defaults to 3, and url defaults to "https://maps.googleapis.com/maps/api/js".
class Loader {
/**
* Creates an instance of Loader using LoaderOptions.
* @param options - Configuration options for the loader
*/
constructor(options: LoaderOptions);
// Properties (readonly)
readonly version: string;
readonly apiKey: string;
readonly channel: string;
readonly client: string;
readonly id: string;
readonly libraries: Libraries;
readonly language: string;
readonly region: string;
readonly mapIds: string[];
readonly nonce: string | null;
readonly retries: number;
readonly url: string;
readonly authReferrerPolicy: "origin";
// Methods
get options(): LoaderOptions;
get status(): LoaderStatus;
/** @deprecated Use importLibrary() instead */
createUrl(): string;
deleteScript(): void;
/** @deprecated Use importLibrary() instead */
load(): Promise<typeof google>;
/** @deprecated Use importLibrary() instead */
loadPromise(): Promise<typeof google>;
/** @deprecated Use importLibrary() instead */
loadCallback(fn: (e: ErrorEvent) => void): void;
// Library import methods (recommended)
importLibrary(name: "core"): Promise<google.maps.CoreLibrary>;
importLibrary(name: "maps"): Promise<google.maps.MapsLibrary>;
importLibrary(name: "maps3d"): Promise<google.maps.Maps3DLibrary>;
importLibrary(name: "places"): Promise<google.maps.PlacesLibrary>;
importLibrary(name: "geocoding"): Promise<google.maps.GeocodingLibrary>;
importLibrary(name: "routes"): Promise<google.maps.RoutesLibrary>;
importLibrary(name: "marker"): Promise<google.maps.MarkerLibrary>;
importLibrary(name: "geometry"): Promise<google.maps.GeometryLibrary>;
importLibrary(name: "elevation"): Promise<google.maps.ElevationLibrary>;
importLibrary(name: "streetView"): Promise<google.maps.StreetViewLibrary>;
importLibrary(name: "journeySharing"): Promise<google.maps.JourneySharingLibrary>;
importLibrary(name: "drawing"): Promise<google.maps.DrawingLibrary>;
importLibrary(name: "visualization"): Promise<google.maps.VisualizationLibrary>;
importLibrary(name: Library): Promise<unknown>;
}Usage Examples:
import { Loader } from '@googlemaps/js-api-loader';
// Create loader instance
const loader = new Loader({
apiKey: "YOUR_API_KEY",
version: "weekly",
libraries: ["places", "marker"]
});
// Note: Loader uses singleton pattern - creating multiple instances
// with the same options returns the same instance
// Check loading status
console.log(loader.status); // LoaderStatus.INITIALIZED
// Modern library loading (recommended)
const { Map } = await loader.importLibrary('maps');
const { AdvancedMarkerElement } = await loader.importLibrary('marker');
// Create map and marker
const map = new Map(document.getElementById("map"), {
center: { lat: 37.4419, lng: -122.1419 },
zoom: 8,
mapId: "DEMO_MAP_ID"
});
const marker = new AdvancedMarkerElement({
map,
position: { lat: 37.4419, lng: -122.1419 }
});Configuration interface for the Loader constructor.
interface LoaderOptions {
/** Google Maps API key (required) */
apiKey: string;
/** API version: "weekly", "quarterly", or specific version like "3.40" */
version?: string;
/** Script tag ID (default: "__googleMapsScriptId") */
id?: string;
/** Array of libraries to load (default: []) */
libraries?: Libraries;
/** Language code for localization */
language?: string;
/** Region code for geocoding bias */
region?: string;
/** Custom API script URL (default: "https://maps.googleapis.com/maps/api/js") */
url?: string;
/** CSP nonce attribute */
nonce?: string;
/** Number of retry attempts on failure (default: 3) */
retries?: number;
/** HTTP referrer policy for authentication */
authReferrerPolicy?: "origin";
/** @deprecated Premium plan channel */
channel?: string;
/** @deprecated Premium plan client ID, use apiKey instead */
client?: string;
/** @deprecated Map IDs, no longer required */
mapIds?: string[];
}Enumeration representing the current state of the Loader.
enum LoaderStatus {
INITIALIZED = 0, // Loader created but not started
LOADING = 1, // API script loading in progress
SUCCESS = 2, // API script loaded successfully
FAILURE = 3 // API script failed to load
}Type definitions for available Google Maps API libraries.
type Library =
| "core"
| "maps"
| "maps3d"
| "places"
| "geocoding"
| "routes"
| "marker"
| "geometry"
| "elevation"
| "streetView"
| "journeySharing"
| "drawing"
| "visualization";
type Libraries = Library[];const DEFAULT_ID: string = "__googleMapsScriptId";Use importLibrary() for type-safe, granular library loading:
import { Loader } from '@googlemaps/js-api-loader';
const loader = new Loader({ apiKey: "YOUR_API_KEY" });
// Load specific libraries as needed
const { Map } = await loader.importLibrary('maps');
const { PlacesService } = await loader.importLibrary('places');
const { AdvancedMarkerElement } = await loader.importLibrary('marker');⚠️ Deprecated: Use importLibrary() instead
Load the entire Google Maps API using Promise:
loader.load().then((google) => {
const map = new google.maps.Map(document.getElementById("map"), mapOptions);
}).catch(error => {
console.error('Error loading Google Maps:', error);
});⚠️ Deprecated: Use importLibrary() instead
Use callback-based loading:
loader.loadCallback((error) => {
if (error) {
console.error('Failed to load Google Maps:', error);
} else {
const map = new google.maps.Map(document.getElementById("map"), mapOptions);
}
});The loader includes automatic retry logic and comprehensive error handling:
import { Loader, LoaderStatus } from '@googlemaps/js-api-loader';
const loader = new Loader({
apiKey: "YOUR_API_KEY",
retries: 3 // Retry up to 3 times on failure
});
try {
const { Map } = await loader.importLibrary('maps');
// Check final status
if (loader.status === LoaderStatus.SUCCESS) {
// Create map
} else if (loader.status === LoaderStatus.FAILURE) {
// Handle failure
}
} catch (error) {
console.error('Failed to load Google Maps library:', error);
}const loader = new Loader({
apiKey: "YOUR_API_KEY",
url: "https://custom-maps-api.example.com/maps/api/js",
nonce: "your-csp-nonce"
});const loader = new Loader({
apiKey: "YOUR_API_KEY",
language: "ja", // Japanese
region: "JP" // Japan region bias
});const loader = new Loader({
apiKey: "YOUR_API_KEY",
version: "quarterly" // Use stable quarterly release
// or version: "3.40" // Use specific version
});The Loader uses a singleton pattern - creating multiple instances with the same options returns the same instance. Attempting to create a new instance with different options will throw an error:
const loader1 = new Loader({ apiKey: "YOUR_API_KEY" });
const loader2 = new Loader({ apiKey: "YOUR_API_KEY" });
console.log(loader1 === loader2); // true
// Different options will throw an error
try {
const loader3 = new Loader({ apiKey: "DIFFERENT_KEY" });
} catch (error) {
console.error('Cannot create loader with different options:', error.message);
// Error: Loader must not be called again with different options
}