Leaflet
Leaflet is a lightweight, open-source JavaScript library designed for creating mobile-friendly interactive maps. It focuses on performance, usability, and extensibility, providing a core set of features like layers, markers, popups, and controls, while supporting a rich ecosystem of plugins for advanced functionality. The current stable major version is 1.x, with `1.9.4` being the latest bugfix release, which is now in maintenance mode, receiving only critical bugfixes. Development has shifted significantly towards the upcoming 2.0 release, currently in alpha, which modernizes the codebase by dropping Internet Explorer support, removing legacy methods, and fully embracing ES Modules. Its simple API and strong community support make it a popular choice for web mapping applications, particularly where performance and bundle size are critical.
Common errors
-
ReferenceError: L is not defined
cause The Leaflet library was not properly loaded or imported, or you are trying to use `L` in a Leaflet 2.x ESM-only environment without the global bundle.fixFor Leaflet 1.x, ensure `leaflet.js` is loaded via a `<script>` tag or `import 'leaflet'` is used in a bundler setup. For Leaflet 2.x, use named imports like `import { Map } from 'leaflet';` or ensure you are loading the `leaflet-global.js` bundle if you require the global `L`. -
TypeError: Cannot read properties of undefined (reading 'mergeOptions') OR Failed to load resource: the server responded with a status of 404 (Not Found) for marker images.
cause Leaflet's default marker icons cannot be found by the browser, usually because a bundler hasn't correctly resolved the relative image paths from `node_modules`.fixOverride Leaflet's default icon paths to point to absolute URLs (e.g., `L.Icon.Default.mergeOptions({ iconRetinaUrl: 'https://...', iconUrl: 'https://...', shadowUrl: 'https://...' });`) or configure your bundler to copy `node_modules/leaflet/dist/images` to your public asset folder. -
Cannot find module 'leaflet' OR Attempted import error: 'Map' is not exported from 'leaflet'.
cause This can occur in Leaflet 1.x when attempting named imports that are not available, or in 2.x if the environment isn't correctly resolving ES Modules, or trying to use new ESM imports in a 1.x environment.fixFor Leaflet 1.x, rely on the global `L` object or `import * as L from 'leaflet';` in TypeScript. For Leaflet 2.x, ensure your build setup supports ES Modules and use named imports like `import { Map, tileLayer } from 'leaflet';`. If on Leaflet `v1.9.2` or later and explicitly want ESM, import `leaflet/dist/leaflet-src.esm.js`.
Warnings
- breaking Leaflet v2.0 introduces a full conversion to ES Modules, fundamentally changing how the library is imported. The global `L` object is no longer provided by the core package. Legacy CommonJS `require` is also no longer supported for the core.
- breaking Leaflet v2.0 has dropped support for Internet Explorer and removed many legacy methods and polyfills, adopting modern web standards like Pointer Events. This may cause issues in older browser environments or with plugins relying on deprecated APIs.
- gotcha As of v1.9.0, the Leaflet 1.x branch has entered maintenance mode, meaning future releases will be reserved primarily for critical bugfixes. New features and significant development are focused on the 2.x branch.
- gotcha The default ESM entrypoint was temporarily removed from the main package in v1.9.2 due to compatibility issues with plugins. Importing `leaflet` via ESM might not work as expected in some bundlers.
- gotcha When using bundlers (like Webpack, Vite) with Leaflet 1.x, the default marker icons often fail to load because their paths are relative and not correctly handled by the bundler's asset pipeline.
Install
-
npm install leaflet -
yarn add leaflet -
pnpm add leaflet
Imports
- L (global object)
import { L } from 'leaflet';import 'leaflet'; // Makes L globally available (v1.x) // or via script tag: <script src="leaflet.js"></script>
- Named exports (Map, tileLayer, marker)
const L = require('leaflet'); L.map(...);import { Map, tileLayer, marker } from 'leaflet'; - ESM explicit path (v1.9.2+)
import 'leaflet';
import 'leaflet/dist/leaflet-src.esm.js';
- TypeScript types
import * as L from 'leaflet'; // Ensure @types/leaflet is installed: npm install --save-dev @types/leaflet
Quickstart
import 'leaflet/dist/leaflet.css'; // Essential for Leaflet styles
// For TypeScript with bundlers and Leaflet 1.x, `import * as L from 'leaflet';` is common.
// For native browser usage with script tags, `L` is globally available.
import * as L from 'leaflet';
// A common issue in bundlers is that Leaflet's default marker icons aren't correctly resolved.
// We override L.Icon.Default to point to known URLs, preventing missing marker images.
L.Icon.Default.mergeOptions({
iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png'
});
document.addEventListener('DOMContentLoaded', () => {
// Ensure a map div exists
let mapDiv = document.getElementById('map');
if (!mapDiv) {
mapDiv = document.createElement('div');
mapDiv.id = 'map';
mapDiv.style.height = '400px';
mapDiv.style.width = '100%';
document.body.appendChild(mapDiv);
}
// Initialize the map on the 'map' div with a given view and zoom level
const map = L.map('map').setView([51.505, -0.09], 13);
// Add an OpenStreetMap tile layer to the map
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Add a marker to the map at a specific coordinate
L.marker([51.5, -0.09])
.addTo(map)
.bindPopup('A sample marker in London!')
.openPopup();
});