Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proj4 is undefined with ES6 and module import #193

Open
xylolink opened this issue Jan 18, 2018 · 17 comments
Open

Proj4 is undefined with ES6 and module import #193

xylolink opened this issue Jan 18, 2018 · 17 comments
Assignees

Comments

@xylolink
Copy link

xylolink commented Jan 18, 2018

(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 !

@lowzonenose
Copy link
Contributor

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...

@xylolink
Copy link
Author

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.

@lowzonenose
Copy link
Contributor

cf. isssue : umdjs/umd#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
Copy link
Contributor

lowzonenose commented Jan 23, 2018

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
Copy link
Contributor

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

@davidbrochart
Copy link

Je pense avoir un problème similaire, L.Proj n'est pas défini ici:

var crs = new L.Proj.CRS("EPSG:2154",

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

require('geoportal-extensions-leaflet');

@lowzonenose
Copy link
Contributor

lowzonenose commented Sep 14, 2022

@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.

@davidbrochart
Copy link

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

@lowzonenose
Copy link
Contributor

lowzonenose commented Sep 15, 2022

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 ?

@davidbrochart
Copy link

davidbrochart commented Sep 15, 2022

Oui c'est accepté, mais ensuite L.Proj n'est pas défini dans:

var crs = new L.Proj.CRS("EPSG:2154",

Nous n'utilisons pas react.

@lowzonenose
Copy link
Contributor

lowzonenose commented Sep 15, 2022

@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/)

@davidbrochart
Copy link

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.

@lowzonenose
Copy link
Contributor

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 !?

@HaudinFlorence
Copy link

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

@lowzonenose
Copy link
Contributor

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.

@davidbrochart
Copy link

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?

@theodury
Copy link

Any News ?