skip to Main Content

Hello I am building an app which uses the library leaflet.heat. In order to be used it has to be imported as follows:

import * as L from 'leaflet';
import 'leaflet.heat';

...
// Then it can be used:
  private addHeatmapToMap(heatmapData: L.HeatLatLngTuple[]) {
   ...
    let heatmap = L.heatLayer(heatmapData, { radius: 10, max: 200, gradient: { 0.1: 'yellow', 0.4: 'orange', 0.6: 'red', 0.8: 'white' }, minOpacity: 0.8 });
   ...
  }

This works as expected when using ng serve. But when the app is built to be used in a docker container with ng build --configuration production --output-path=/dist the functions that are derived from L. which depend on the import of leaflet.heat stop working.

My first guess is that angular removes the import during the build process because there is no direct use of that import in the component but I have no idea how can I indicate angular to not do that.

The versions used are:

    angular 18:
    ...
    "leaflet": "^1.9.4",
    "leaflet.heat": "^0.2.0",
    ...
    "@types/leaflet": "^1.9.12",
    "@types/leaflet.heat": "^0.2.4",

Dockerfile:

#################
# Build the app #
#################
FROM node:22-alpine AS build

WORKDIR /app

RUN npm install -g @angular/cli

COPY package.json package-lock.json ./
RUN npm install --fetch-timeout=600000 
COPY . .

RUN ng build --configuration production --output-path=/dist

################
# Run in NGINX #
################
FROM nginx:alpine

COPY --from=build /dist/browser /usr/share/nginx/html
COPY --from=build /app/nginx.conf /etc/nginx/nginx.conf

# When the container starts, replace the env.js with values from environment variables
CMD ["/bin/sh",  "-c",  "envsubst < /usr/share/nginx/html/assets/environment/env.template.js > /usr/share/nginx/html/assets/environment/env.js && exec nginx -g 'daemon off;'"]

2

Answers


  1. The library probably was tree shaken and removed when you ran angular build with optimizations.

    First we need to add this script to assets folder, which is also a configuration on the assets array of angular.json.

    Then import the script explicitly through the scripts folder of angular.json.

    angular.json:

      ...
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/app",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": ["zone.js"],
            "tsConfig": "tsconfig.app.json",
            "inlineStyleLanguage": "scss",
            "assets": [ 
              "src/favicon.ico", 
              "src/assets", 
              "./node_modules/leaflet.heat/dist/leaflet-heat.js"
            ],
            "styles": ["src/styles.scss"],
            "scripts": [
              ...
              "src/assets/leaflet-heat.js",
              ...
            ]
          },
          ...
    
    Login or Signup to reply.
  2. Maybe you are not properly installing the project dependencies upon creating the Dockerfile? But if that’s not the problem, I’d use the scripts array in angular.json:

    "scripts": [
      "node_modules/leaflet/dist/leaflet.js",
      "node_modules/leaflet.heat/dist/leaflet-heat.js"
    ]
    

    Or you can make sure Angular does not remove that in tree-shaking by importing it as a side effect.

    import * as L from 'leaflet';
    import 'leaflet.heat/dist/leaflet-heat.js';
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search