OpenLayers Deployment & Usage Guide
Prerequisites
- Node.js: Version 16.x LTS or higher (18.x recommended)
- Package Manager: npm (included with Node.js), yarn, or pnpm
- Browser: Modern browser with >1% global usage (Chrome, Firefox, Safari, Edge)
- Build Tool: One of Vite, webpack, Rollup, or Parcel (Vite recommended for new projects)
- Optional: TypeScript 4.5+ (type declarations included in
olpackage)
Installation
NPM Package (Recommended)
# Create new project directory
mkdir my-map-app && cd my-map-app
npm init -y
# Install OpenLayers
npm install ol
# Install development server (Vite example)
npm install --save-dev vite
CDN/No-Build Setup (Prototyping)
For quick prototyping without Node.js, use Skypack:
<!DOCTYPE html>
<html>
<head>
<script type="module">
import Map from 'https://cdn.skypack.dev/ol/Map.js';
import View from 'https://cdn.skypack.dev/ol/View.js';
import TileLayer from 'https://cdn.skypack.dev/ol/layer/Tile.js';
import OSM from 'https://cdn.skypack.dev/ol/source/OSM.js';
new Map({
target: 'map',
layers: [new TileLayer({source: new OSM()})],
view: new View({center: [0, 0], zoom: 2})
});
</script>
</head>
<body>
<div id="map" style="width: 100%; height: 100vh;"></div>
</body>
</html>
Configuration
Basic Map Configuration
Create main.js (or main.ts):
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import {fromLonLat} from 'ol/proj';
const map = new Map({
target: 'map', // DOM element ID
layers: [
new TileLayer({
source: new OSM({
// Optional: Custom tile URL (requires attribution)
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
attributions: '© OpenStreetMap contributors'
})
})
],
view: new View({
center: fromLonLat([-74.006, 40.7128]), // NYC example
zoom: 12,
maxZoom: 19,
minZoom: 2
})
});
Environment Variables (Optional)
For API keys (Mapbox, etc.), create .env:
VITE_MAPBOX_API_KEY=your_key_here
Access in code:
const mapboxKey = import.meta.env.VITE_MAPBOX_API_KEY;
TypeScript Configuration
tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
Build & Run
Vite (Recommended)
# Install
npm install --save-dev vite
# Development server
npx vite
# Production build
npx vite build
# Output: dist/ directory
Webpack
# Install dependencies
npm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin
# Development
npx webpack serve --mode development
# Production build
npx webpack --mode production
# Output: dist/ directory
Rollup
# Install
npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs
# Build
npx rollup -c
Parcel
# Install
npm install --save-dev parcel
# Development
npx parcel index.html
# Production
npx parcel build index.html
Deployment
OpenLayers applications are client-side only and deploy as static sites.
Build Output
Ensure your build produces:
index.html- Bundled JavaScript (e.g.,
assets/index-*.js) - Any static assets (images, fonts, data files)
Platform-Specific Deployment
Vercel (Zero-config):
npm install -g vercel
vercel --prod
# Set framework preset to "Vite" or "Other" if prompted
Netlify (Drop or CLI):
# Build first
npx vite build
# Deploy via CLI
npm install -g netlify-cli
netlify deploy --prod --dir=dist
GitHub Pages:
# Add to package.json
"homepage": "https://username.github.io/repo-name",
# Build and deploy
npx vite build
git add dist && git commit -m "Add dist"
git subtree push --prefix dist origin gh-pages
AWS S3 + CloudFront:
# Sync build output to S3 bucket
aws s3 sync dist/ s3://your-bucket-name --delete
# Invalidate CloudFront cache (if using)
aws cloudfront create-invalidation --distribution-id YOUR_ID --paths "/*"
Environment Configuration
For production builds, ensure:
NODE_ENV=productionis set- Source maps disabled for public builds (optional)
- API keys restricted to production domains
Troubleshooting
Module Resolution Errors
Error: Cannot find module 'ol/Map'
- Solution: Ensure
olis installed:npm list ol - Check
package.jsonhas"type": "module"or use.mjsextension - For TypeScript, ensure
moduleResolutionis set to"node"or"bundler"
CORS Issues with Tile Layers
Error: Tiles not loading, console shows CORS errors
- Solution: Configure tile server CORS headers, or use proxy
- For WMS/WFS layers, ensure server supports CORS or use
crossOrigin: 'anonymous':
new TileLayer({
source: new XYZ({
url: '...',
crossOrigin: 'anonymous'
})
})
Performance Issues with Large Datasets
Symptom: Slow rendering with many vector features
- Solution:
- Use
VectorImagelayer instead ofVectorfor static data - Implement clustering:
new Cluster({source: vectorSource}) - Use WebGL layers for large datasets (WebGLPointsLayer, WebGLTileLayer)
- Enable loading strategies:
strategy: bboxfor WFS sources
- Use
WebGL Context Lost
Error: "WebGL context lost" in console, map disappears
- Solution:
- Reduce concurrent WebGL contexts (limit maps on page)
- Handle context restoration:
map.on('webglcontextlost', (event) => {
event.preventDefault();
console.warn('WebGL context lost');
});
Projection Mismatches
Error: Features appear in wrong location or not at all
- Solution:
- Ensure view projection matches data projection
- Use
fromLonLat()for EPSG:4326 to EPSG:3857 (Web Mercator) conversion - Register custom projections if needed:
proj4.defs('EPSG:3006', '...')
TypeScript Declaration Issues
Error: Type definitions not found or incorrect
- Solution:
- Ensure
skipLibCheck: truein tsconfig.json - Import types explicitly:
import type {Map} from 'ol' - Check
olpackage version matches type expectations
- Ensure