Search code examples
javascripttypescriptwebpackleafletbundling-and-minification

Using Leaflet or any js library with Typescript and webpack


Note: I have searched a lot but I couldn't find my answer.

I am trying to create a map library by extending leaflet. But I think my problem is with using js libraries in general. I am using webpack and ts-loader to create the output file.

I have installed the types @types/geojson and @types/leaflet and moved them to modules folder.

here is my simple Test1.ts file :

import * as L from './modules/@types/leaflet/index';
import { MyDataItem } from './MyDataItem ';

export class Test1 {
    text: string;
    data: MyDataItem ;
    latLng: L.LatLng;
   
    constructor(theName: string) {
        this.data = { name: theName} as MyDataItem ;
    }
    public show() {
        console.log(this.data.name);
    }

    public showLatLng() {
        this.latLng = new L.LatLng(22, 55);
        console.log(this.latLng);
    }
}

module.exports = {
    Test1: Test1
}

I set library:'lib' in my webpack output option. now I call the following methods from my browser console:

> (new lib.Test1("aa")).show()        // result: aa
> (new lib.Test1("aa")).showLatLng()   // error : L.LatLng is not a constructor
// or if it set webpack optimization:minimize to true  the error is: i.LatLng is not a constructor

I have added leaflet.js to the page so typeof(L.latlng) is "function" (latlng with small letters).

Question: obviously the types that I used from leaflet are not accessible after generating js files. My assumption was if you create ts declaration file (.d.ts) for any js library you can use that library in your ts files. what am I missing here? How to add and use normal js libraries in Typescript file so that they work after bundling them with webpack?


Solution

  • The usual practice is to install both leaflet and its associated @types/leaflet packages in your node_modules folder, and to just import * as L from "leaflet" (or just import L from "leaflet", depending on your webpack configuration). The types will be automatically visible. And webpack will automatically bundle Leaflet.

    Same for all other JS libraries.

    By importing just the types (import * as L from './modules/@types/leaflet/index';), you do tell TypeScript what L means, but not webpack.

    If for some reason you really want to add the Leaflet library by yourself, instead of letting webpack bundling it with the rest of your application, then you have to tell webpack to leave L as it is, because you will provide it in global scope somehow. Configure webpack with externals, e.g.:

    module.exports = {
      //...
      externals : {
        "./modules/@types/leaflet/index": {
          root: 'L' // indicates global variable
        }
      }
    };