Skip to content

Web GIS

Making a beautiful map requires a lot of effort. If your map is only for illustration, you may only need a printed or static digital version.

However, expectations have evolved. People today expect their maps to be more engaging, interactive, and accessible. They are looking for maps with dynamic content that encourage exploration and provide more profound insights.

Web GIS can help with that, but depending on what you're trying to achieve, implementing Web GIS at your organization can get quite technical.

Web GIS combines the power of the browser and GIS tools for capturing, storing, and analyzing spatial data, enabling users to access spatial data from anywhere, on any device.

Below are some key considerations that we'll explore in this chapter for a successful Web GIS mapping application:

  • Choose a web mapping library that suits your needs
  • Decide on writing an app with plain JavaScript or a frontend web development framework and build tool
  • Assuming your data has already been preprocessed and ready for publishing on the web, consider where you will host your data
    • Client side or server side?

Web mapping libraries

To include maps in a web application, the easiest and most common way is through mapping libraries. Mapping libraries provide out-of-the-box support for visualizations and interactions in maps. Here are some popular web mapping libraries:

Choosing the best web mapping libraries that suit end user and developer needs is a crucial step for all web development involving maps and/or location services.

TIP

You should check out all the different lessons on this site for examples of a few of these libraries. The projections page uses D3, the scale page uses Leaflet and the types of maps page uses the ArcGIS Maps SDK for JavaScript at the bottom. Leaflet and the ArcGIS Maps SDK for JavaScript are on this page too. You can usually tell which technology was used to author a web map by looking at the attribution at the bottom of the map.

Frontend web development frameworks

Your choice of a frontend framework can depend on the scale of the website you plan to host your web mapping application on. Some web maps can be quite simple like placing a point on a map to help customers find a business. For this, the application can be written quickly without extra tools, all you need is HTML/JavaScript/CSS.

TIP

If you're new to web development, you should read about the Document Object Model (DOM), HTML, JavaScript, and CSS. MDN Web Docs, by Mozilla, are a great resource for learning web development.

html
<html>
  <head>
    <!-- Page title shown in browser tab -->
    <title>Simple Leaflet Map</title>
    <meta charset="utf-8" />
    <!-- Responsive design for mobile devices -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- Custom stylesheet for map styling -->
    <link rel="stylesheet" href="style.css" />
    <!-- Leaflet CSS for map appearance -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
    <!-- Leaflet JS library for interactive maps -->
    <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
  </head>
  <body>
    <!-- Container for the Leaflet map -->
    <div id="map"></div>
    <!-- Custom JavaScript for map initialization and interaction -->
    <script src="script.js"></script>
  </body>
</html>
javascript
// Initialize the map and center on Victoria, BC
var map = L.map("map").setView([48.46, -123.36], 14);

// Add OpenStreetMap tiles
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  attribution: "© OpenStreetMap contributors",
}).addTo(map);

// Add a marker
L.marker([48.46, -123.36])
  .addTo(map)
  .bindPopup("Find our cafe here!")
  .openPopup();
css
#map {
  height: 100vh;
  width: 100%;
}

What you saw above is great, but it's important to remember that there are organizations out there that intentionally build applications meant to scale with demands and complexity. If you want to scale quickly along with a team, writing a scalable web application requires structure, organization, and maintainability.

Fortunately, you don't need to decide on structure and tooling yourself. Frameworks make app development easier by providing more structure to the way we write applications. They do come with a learning curve, but in return you get a more maintainable codebase, reusable components, nice conveniences, and helpful tooling. These benefits can really pay off as your project grows along with you and your team.

There are a lot of front-end frameworks to choose from. Some of the most popular are React, Vue, and Angular. There are some nuances, but generally, frontend frameworks encourage component-based/reusable code block architecture via a top-down, one-way data flow which involves passing information from parent components to their children. In turn, frontend frameworks promote declarative code writing (e.g., more HTML and less JavaScript).

TIP

Be sure to read up on Node.js, npm, package.json, dependencies, devDependencies, and semantic versioning before you start working with frameworks.

Before the ArcGIS Maps SDK for JavaScript introduced their new library of web components in version 4.28, widgets based on proprietary technology were the only means for adding UI to your web application. Implementing widgets in an app required a lot of boilerplate code and was imperative in nature.

What are web components?

Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web pages and web apps. Custom components built on Web Component standards will work across modern browsers, and can be used with any JavaScript library or framework that works with HTML. Web components are based on existing web standards, letting web developers easily extend HTML with new elements with encapsulated styling and custom behavior.

Interested in writing your own web components using a web mapping library? Check out these resources about the process:

The ArcGIS Maps SDK for JavaScript's switch from an imperative API for UI to a community standards-based component library makes it easier to use in plain JavaScript and frontend frameworks. Check out the code sample below showing the SDK with imperative widgets versus declarative web components in plain JavaScript.

html
<body>
  <div id="viewDiv"></div>
  <script>
    require([
      "esri/views/MapView",
      "esri/widgets/Legend",
      "esri/widgets/Search",
      "esri/WebMap",
    ], (MapView, Legend, Search, WebMap) => {
      const webmap = new WebMap({
        portalItem: {
          id: "11e173a4e2f040ae80d39e44ee29467a",
        },
      });
      const view = new MapView({
        container: "viewDiv",
        map: webmap,
      });
      const search = new Search({
        view,
      });
      const legend = new Legend({
        view,
      });
      view.ui.add(search, "top-right");
      view.ui.add(legend, "bottom-left");
    });
  </script>
</body>
html
<body>
  <arcgis-map item-id="11e173a4e2f040ae80d39e44ee29467a">
    <arcgis-search position="top-right" />
    <arcgis-legend position="bottom-left" />
  </arcgis-map>
</body>

Framework-based mapping libraries

There are a growing number of JavaScript mapping libraries as reusable code blocks of React, Angular, web, or Vue components. Some notable component libraries are:

The challenge with mapping libraries lacking framework-agnostic web components is that committing to one framework can make switching difficult, or the library might not even offer support for your desired framework. This scenario often requires you to build all the necessary UI components yourself.

Tooling

HTML/CSS/JavaScript are core features of modern web browsers. Frameworks like React or Vue extend these native web technologies.

Bundlers like Vite optimize and prepare framework-based applications for browsers by reducing file sizes and splitting bundles.

What do bundlers do?

What do bundlers do?

Furthermore, adding TypeScript to frontend frameworks like React provides an improved developer experience. TypeScript's static typing adds a layer of safety to JavaScript development, reducing uncertainty and boosting confidence.

Code sample

Check out this code repository combining the ArcGIS Maps SDK for JavaScript with React, Vite, and TypeScript.

Rendering strategies

As opposed to client-side rendering (CSR) like many existing React applications on the web today, static site generators (SSG) such as Astro, Nuxt, and Next.js offer advantages like search engine optimization (SEO), simplified page routing and server-side rendering (SSR). However, mapping libraries are often problematic when integrated with SSR environments due to their reliance on the browser's window object, which is unavailable during SSR. You might find yourself needing to write workarounds when trying to use web mapping functionalities within SSG-based applications.

This is what could be done to get Leaflet to work in a SSG-based application.

vue
<script setup>
import { onMounted } from 'vue';
let Leaflet;

onMounted(async () => {
  // Import dynamically to avoid window not defined error in SSR
  Leaflet = await import('leaflet'); 

  // Check if window is defined
  if (typeof window !== 'undefined') {
    const map = Leaflet.map('map').setView([48.43, -123.36], 14);

    Leaflet.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    Leaflet.marker([48.43, -123.36])
      .addTo(map)
      .bindPopup('Find our cafe here!')
      .openPopup();
  }
});
</script>
vue
<script setup>
import { onMounted } from 'vue';
// Direct import in CSR
import * as Leaflet from 'leaflet';

onMounted(() => {
  const map = Leaflet.map('map').setView([48.43, -123.36], 14);

  Leaflet.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map);

  Leaflet.marker([48.43, -123.36])
    .addTo(map)
    .bindPopup('Find our cafe here!')
    .openPopup();
});
</script>

You won't allows need to write this kind of workaround. See VitePress <ClientOnly> or Astro client directives for simpler workarounds.

TIP

This site was built with VitePress which is a Vite and Vue powered SSG. You can check out all the code for this site here.

If you're interested in SEO, you should read up Vercel's research of how Google handles JavaScript through the indexing process based on different rendering strategies.

Client-side/server-side data

When a user visits a web mapping application, the application can load spatial data on the client-side directly in the user's browser. For example, with Leaflet, you can load a CSV or GeoJSON file directly into the map. This is ideal for small datasets or offline use in disconnected/air gapped environments. CSR, as covered in rendering strategies above, often uses client-side data.

javascript
import * as L from 'leaflet';

const map = L.map("map").setView([48.43, -123.36], 14);

fetch('points.geojson')
  .then(response => response.json())
  .then(data => {
    L.geoJSON(data).addTo(map);
  });

Server-side data is more scalable for enterprise/large company needs because it is hosted externally and accessible via APIs or services on a remote server or cloud service.

You can load web maps and other geospatial data that you make with Map Viewer directly from ArcGIS Online or connect to your own hosted GIS services using the ArcGIS Maps SDK for JavaScript. Map Viewer is a feature of ArcGIS Online and ArcGIS Enterprise that aims to simplify the creation and sharing of web maps.

html
<body>
  <arcgis-map id="map">
    <arcgis-zoom position="top-left"></arcgis-zoom>
  </arcgis-map>
  <script type="module" src="main.js"></script>
</body>
javascript
import Map from "@arcgis/core/Map.js";
import Layer from "@arcgis/core/layers/Layer.js";

const viewElement = document.getElementById("map");

viewElement.addEventListener("arcgisViewReadyChange", async (event) => {
  const layer = await Layer.fromPortalItem({
    portalItem: {
      id: "11e173a4e2f040ae80d39e44ee29467a",
    },
  });
  viewElement.map = new Map({
    basemap: "topo-vector",
    layers: [layer],
  });
  viewElement.center = [-73.97, 40.77];
  viewElement.zoom = 10;
});

Self-hosting requires setting up a GIS server (such as ArcGIS Enterprise or GeoServer), caching, maintenance, publishing services, understanding relational databases, and managing authentication and access, whereas loading from a paid service like ArcGIS Online is simple.

Loading data from a server isn't limited to the ArcGIS Maps SDK for JavaScript. You can do something similar with OpenLayers and GeoServer.

javascript
import Vector from 'ol/source/Vector.js';
import GeoJSON from 'ol/format/GeoJSON.js';
import { bbox } from 'ol/loadingstrategy.js';

// Load vector data from a remote GeoServer using WFS and GeoJSON
const vectorSource = new Vector({
  format: new GeoJSON(),
  loader: function(extent, resolution, projection, success, failure) {
    const proj = projection.getCode();
    const url = 'https://ahocevar.com/geoserver/wfs?service=WFS&' +
      'version=1.1.0&request=GetFeature&typename=osm:water_areas&' +
      'outputFormat=application/json&srsname=' + proj + '&' +
      'bbox=' + extent.join(',') + ',' + proj;
    fetch(url)
      .then(response => response.json())
      .then(data => {
        const features = vectorSource.getFormat().readFeatures(data);
        vectorSource.addFeatures(features);
        success(features);
      })
      .catch(() => {
        vectorSource.removeLoadedExtent(extent);
        failure();
      });
  },
  strategy: bbox,
});

Test your knowledge

0 of 3 correct

For a simple web map to display a business location, which might be sufficient?

Next steps

WARNING

Exercise for how to host your own web mapping application via GitHub Pages is a work in progress.

Released under the GPL-3.0 license.