geoportal-extensions icon indicating copy to clipboard operation
geoportal-extensions copied to clipboard

Proj4 is undefined with ES6 and module import

Open xylolink opened this issue 7 years ago • 17 comments

(Je ne sais pas si la convention ici est de s'exprimer en Fr ou en En... A défaut je vais opter pour l'en) Hi, It seems not possible to load this package with ES6 modules. In my configuration, the package is installed with npm and my JS is compiled with webpack (using babel plugin).

Importing Gp results in a "proj4 is not defined" error. I tried to install and load proj4, but it results in the same issue.

Is it possible to load the package with ES6 modules ? What should I do to manage the proj4 dependancy ? I have no other solution as I want to integrate this module with react-js and react-leaflet.

Thanks !

A priori tous les messages sont rédigés en Français, je traduis donc ici : Bonjour, Il est a priori impossible de charger ce paquet avec les modules (import/export) d'ES6. J'ai installé le paquet avec npm, mon code est compilé via webpack et utilise le plugin babel.

Quand je fais un "import 'Gp' from 'geoportal-extensions-leaflet'" j'ai une erreur au chargement de la page m'indiquant que "proj4 is undefined" J'ai essayé de charger proj4 via un 'import', le résultat est le même.

Est-ce que l'un d'entre vous a déjà chargé le paquet avec les modules ES6 ? Que dois-je faire pour ne plus avoir ce problème de dépendance ? Il me sera difficile de passer par une autre solution, toute mon appli est bâtie en ES6 avec les modules. D'autant plus que je comptais intégrer l'extension avec react-js et react-leaflet.

Si vous avez une idée pour résoudre ce problème... D'avance merci !

xylolink avatar Jan 18 '18 22:01 xylolink

Bonjour, Je pense que nous avons un problème avec la construction du bundle avec requireJS / Umd pour une utilisation via un import ES6. La variable 'proj4' ne semble pas être globale au moment du changement !? Je vais regarder de plus près...

lowzonenose avatar Jan 19 '18 17:01 lowzonenose

Ok merci, j'attends votre retour. En attendant j'ai créé ma propre interface de gestion des couches. Mais les fonctionnalités de requête de votre extension m'économiseraient pas mal de temps de travail. Je peux faire des tests si besoin.

xylolink avatar Jan 19 '18 20:01 xylolink

cf. isssue : https://github.com/umdjs/umd/issues/124

Test avec l'API des services (https://github.com/IGNF/geoportal-access-lib)

Exemple d'appel du bundle UMD des services dans un module ES6 (import) :

<html>
    <head>
        <script type="module">

            // old synthax
            import * as Gp from '../../../dist/GpServices-src.js';

                var options = {
                    apiKey : 'jhyvi0fgmnuxvfv0zjzorvdn',
                    onSuccess : function (response) {console.log(response.elevations);},
                    // spécifique au service
                    positions : [{lon:1.25, lat:47.48}]
                };

                // call self = window to get Gp (globale !)
                self.Gp.Services.getAltitude(options);

            </script>
    </head>
    <body>
        <h1>Utilisation du service Alti en mode ES6 import</h1>
        <span>(Ouvrir la console)</span>
    </body>
</html>

Pour fonctionner, on modifie l'entête UMD du bundle des services (compatible AMD, Node, Browser et ES6) :

;(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['require', 'require'], factory);
  } else if (typeof exports === 'object' && typeof module === 'object') {
    module.exports = factory(require('request'), require('xmldom'));
  } else if(typeof exports === 'object') {
	exports["Gp"] = factory(require('request'), require('xmldom'));
  } else {
    root.Gp = factory(root.request, root.xmldom);
  }
}(typeof self !== 'undefined' ? self : this, function(request, xmldom) {
 (...)
 return Gp;
});

lowzonenose avatar Jan 23 '18 16:01 lowzonenose

Nos header UMD ne sont pas conformes avec une utilisation dans ES6 module : https://www.npmjs.com/package/gulp-umd https://www.npmjs.com/package/gulp-library-umd

on veut générer ce type de header (https://github.com/umdjs/umd/blob/master/templates/commonjsStrictGlobal.js) :

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module. 
    
    define(["libA","libBAMD"], factory);
  } else if (typeof module === 'object' && module.exports) {
    // Node. Does not work with strict CommonJS, but 
    // only CommonJS-like environments that support module.exports, 
    // like Node. 
    
    module.exports = factory(require("libA"), require("libB"));
  } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
    // CommonJs 
    
    (function (results) {
      
      for (var key in results) {
        if ({}.hasOwnProperty.call(results, key))
          exports[key] = results[key];
      }
      
    })(factory(require("libA"), require("libBCJS")));
  } else {
   // Browser globals 
   
   root.myModuleGlobal = factory(root.libA, root.libBWeb);
  }
}(typeof self !== 'undefined' ? self : this, function (libA,libB) {

}));

lowzonenose avatar Jan 23 '18 17:01 lowzonenose

En attente de la livraison de l'API des services en version 1.1.1.

lowzonenose avatar Feb 06 '18 14:02 lowzonenose

Je pense avoir un problème similaire, L.Proj n'est pas défini ici: https://github.com/IGNF/geoportal-extensions/blob/56d60c599363b6d1f53486b5f557b57af175bc81/src/Leaflet/CRS/EPSG2154.js#L41

Dans un projet CommonJS, où l'extension est importée comme ceci:

require('geoportal-extensions-leaflet');

davidbrochart avatar Sep 14 '22 15:09 davidbrochart

@davidbrochart

Cf. Exemples d'utilisation des extensions dans un projet Front-End : https://github.com/IGNF/geoportal-third-party-integration

Ce n'est pas toujours à jour, mais ça pourrait vous aider.

lowzonenose avatar Sep 14 '22 16:09 lowzonenose

À première vue aucun des ces exemples ne correspond à mon cas d'utilisation. L'ajout de require('geoportal-extensions-leaflet') ne semble pas marcher.

davidbrochart avatar Sep 14 '22 18:09 davidbrochart

Pourtant, l’entête du bundle accepte le commonJS :

(function webpackUniversalModuleDefinition(root, factory) {
        if(typeof exports === 'object' && typeof module === 'object')
                module.exports = factory(require("leaflet"), require("node-fetch"), require("xmldom"));
        else if(typeof define === 'function' && define.amd)
                define("Gp", ["leaflet", "require", "require"], factory);
        else if(typeof exports === 'object')
                exports["Gp"] = factory(require("leaflet"), require("node-fetch"), require("xmldom"));
        else
                root["Gp"] = factory(root["L"], root[undefined], root[undefined]);
})(this, function(__WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__54__, __WEBPACK_EXTERNAL_MODULE__55__) {
...
}

Pourquoi ne pas utiliser l'import dans react ?

lowzonenose avatar Sep 15 '22 11:09 lowzonenose

Oui c'est accepté, mais ensuite L.Proj n'est pas défini dans: https://github.com/IGNF/geoportal-extensions/blob/56d60c599363b6d1f53486b5f557b57af175bc81/src/Leaflet/CRS/EPSG2154.js#L41

Nous n'utilisons pas react.

davidbrochart avatar Sep 15 '22 13:09 davidbrochart

@davidbrochart

L.Proj est mis en place par la lib proj4leaflet (v1.0.2) Et, cette lib est intégrée au bundle.

Il me faudrait plus d'informations pour vous aider. Par exemple, m'envoyer un lien vers une sandbox Js (https://codesandbox.io/ ou https://jsfiddle.net/)

lowzonenose avatar Sep 15 '22 19:09 lowzonenose

Ce n'est pas si simple de faire une sandbox JS, JupyterLab a son propre système de build. Il faut faire une installation de développement d'ipyleaflet à partir de cette PR. Puis ouvir un des exemples de notebook dans JupyterLab. Je peux vous aider si vous voulez, lors d'un call video par exemple.

davidbrochart avatar Sep 15 '22 20:09 davidbrochart

Ce n'est pas si simple de faire une sandbox JS, JupyterLab a son propre système de build. Il faut faire une installation de développement d'ipyleaflet à partir de cette PR. Puis ouvir un des exemples de notebook dans JupyterLab. Je peux vous aider si vous voulez, lors d'un call video par exemple.

je vais regarder votre intégration. Mais, il semble déjà que l'entête généré par notre build (webpack) sur la dépendance proj4leaflet ne soit pas conforme avec un appel require. Je vais donc essayer de comprendre pourquoi webpack fait la bêtise de vouloir modifier l'entête UMD initial !?

lowzonenose avatar Sep 16 '22 09:09 lowzonenose

Bonjour, Est-ce que vous avez pu investiguer ce qui pose souci dans l'intégration? Merci.

HaudinFlorence avatar Oct 04 '22 16:10 HaudinFlorence

Bonjour, Est-ce que vous avez pu investiguer ce qui pose souci dans l'intégration? Merci.

Je viens d'installer l'env de dev d'ipyleaflet à partir de la PR.

J'ai joué qq exemples.

L'exemple examples/GeoportalLayers.ipynb ne fonctionne pas, mais je ne sais pas où consulter les sorties d’exécutions des exemples ou debugger en mode pas à pas ce type d'application, car je ne suis pas très familiarisé avec ce type de Framework.

Peut être qu'une petite aide serait nécessaire...


Sinon, l'idée est de savoir pourquoi L.Proj de la lib. proj4leafet n'est pas ajouté à la structure L de leaflet. Une des piste est de déterminer si require('proj4leaflet'); est bien exécuté ou pourquoi la version embarquée de proj4leaflet ne fait pas le job.

lowzonenose avatar Oct 31 '22 01:10 lowzonenose

Mais, il semble déjà que l'entête généré par notre build (webpack) sur la dépendance proj4leaflet ne soit pas conforme avec un appel require.

Apparemment vous aviez une piste, ce n'était pas une problème finalement?

davidbrochart avatar Nov 02 '22 08:11 davidbrochart

Any News ?

theodury avatar Aug 15 '23 13:08 theodury