skip to Main Content

I’m building a JavaScript app with the ArcGis JavaScript SDK. We have a requirement that the app should run on prem without external dependencies. How can I use the SDK without it making calls to js.arcgis.com?

here is my package.json

{
  "engines": {
    "npm": ">=10.8.3 <=10.8.3",
    "node": ">=22.9.0 <=22.9.0"
},
  "name": "buildingmonitor",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
  "dev": "vite",
  "build": "tsc -b && vite build && npm run copyAssets",
  "lint": "eslint .",
  "preview": "vite preview --port 5173",
  "postinstall": "npm run copyAssets",
  "copyAssets": "shx mkdir -p ./public/assets && shx cp -r node_modules/@esri/calcite-components/dist/calcite/assets/* ./public/assets/",
  },
  "dependencies": {
    "@arcgis/map-components-react": "^4.31.6",
    "@esri/arcgis-rest-auth": "^3.7.0",
    "@esri/arcgis-rest-request": "^4.2.3",
    "@esri/calcite-components-react": "^2.13.2",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router": "^7.0.2"
  },
  "devDependencies": {
    "@eslint/js": "^9.15.0",
    "@types/node": "^22.10.2",
    "@types/react": "^18.3.12",
    "@types/react-dom": "^18.3.1",
    "@types/react-modal": "^3.16.3",
    "@vitejs/plugin-react": "^4.3.4",
    "eslint": "^9.16.0",
    "eslint-plugin-react": "^7.37.2",
    "eslint-plugin-react-hooks": "^5.0.0",
    "eslint-plugin-react-refresh": "^0.4.14",
    "globals": "^15.12.0",
    "shx": "^0.3.4",
    "typescript": "~5.6.2",
    "typescript-eslint": "^8.15.0",
    "vite": "^6.0.0"
  }
}

When I look at my network tab I can see a lot of calls to js.argis.com, and I found that domain hard coded in arcgis node modules folders:
node modules code search

When I inspect my app with dev tools, I see a lot of network calls to js.arcgis.com:
network tab screenshot

Map Widget:

import "@arcgis/map-components/dist/components/arcgis-map";
import { ArcgisMap } from "@arcgis/map-components-react";
import { ArcgisMapCustomEvent } from "@arcgis/map-components/dist/types";

const MapWidget = () => {
  const handleMapReady = (event: ArcgisMapCustomEvent<void>) => {};

  return (
    <ArcgisMap
      onArcgisViewReadyChange={handleMapReady}
    />
  );
};

export default MapWidget;

2

Answers


  1. Chosen as BEST ANSWER
    • Download the ArcGIS JavasScript library

    • unzip and copy the contents into your react app public folder

    • create a service-worker.js file:

      self.addEventListener('install', (event) => {
        const extendableEvent = event;
        extendableEvent.waitUntil(self.skipWaiting());
      });
      
      
      self.addEventListener('activate', (event) => {
        const extendableEvent = event;
        extendableEvent.waitUntil(self.clients.claim());
      });
      
      self.addEventListener('fetch', (event) => {
        console.log('Intercepting request:', event.request.url);
        try{
      
          const fetchEvent = event;
          const url = new URL(fetchEvent.request.url);
          if (url.href.startsWith('https://js.arcgis.com')) {
            console.log("rewriting url", url.href);
            const newUrl = url.href.replace('https://js.arcgis.com', `${self.location.protocol}//${self.location.hostname}:${self.location.port}/arcgis/javascript`);
            console.log("new url", newUrl);
            fetchEvent.respondWith(
              fetch(newUrl, {
                mode: 'cors', // Ensure CORS mode is set
                credentials: 'same-origin', // Include credentials if needed
                headers: {
                  ...fetchEvent.request.headers,
                  'Origin': self.location.origin // Set the Origin header
                }
              })
            );
          } else {
            fetchEvent.respondWith(fetch(fetchEvent.request));
          }
        } catch(err){
          console.error(err);
        }
      });
      
      
      
      
    • register the service worker before creating you app root

      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('/service-worker.js', {scope: `/`}) 
          .then((registration) => {
            console.log('Service Worker registered with scope:', registration.scope);
          })
          .catch((error) => {
            console.error('Service Worker registration failed:', error);
          });
      }
      

  2. When building from npm, and to use local assets there are two steps: (1) copying the assets and (2) configure the asset paths in your code/

    It looks like you’re only doing step 1. You need to also set the assets path.

    The hardcoded paths you’re seeing is just the default.

    Refs:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search