Quel backend pour une application Ionic

Bonjour,

J’aimerai développer une application avec ionic. Cette application permettra d’envoyer des messages à différents utilisateurs (avec un système de push notification). Elle permettra également d’uploader des photos.
Je suppose qu’il me faut une solution back-end à cette application. Avec ionic, je ne sais pas quelle solution est la plus conseillée. J’aimerais choisir une solution gratuite qui propose le plus de services (max de requêtes/jour, capacité de stockage, push…). Je suis un peu perdu avec toutes les solutions qui existent (firebase, backand, parse…)

1 J'aime

Salut

J’ai été dans la meme situation que toi pour 2 apps :

  • une app mobile Ionic
  • une app web en SaaS sur AngularJS.

Donc j’en profite pour te livrer plus en détails mon expérience :

Pour les 2 j’ai opté pour un MBaaS : en gros c’est un backend prêt à l’emploi pour les frontends web (SaaS, mobile hybride).
Ca peut tout aussi bien marcher pour du desktop (Electron, NW) puisque ca reste du web encapsulé.

Pourquoi pas avoir utilisé un framework server-side classique ?
J’avais l’expérience sur un framework PHP (Laravel 5) , mais je voulais me concentrer sur le frontend. De plus coder un backend Laravel n’avait pas de valeur ajoutée sur le projet.
Last but not least, le MBaaS donne accès à des infos pas seulement techniques, mais aussi des infos d’analytics pour les commerciaux et autres non techs. Pas besoin de passer 4 mois a coder en plus un dashboard spécifique.

Concrètement j’ai pris Parse.com qui est sans doute l’un des des plus aboutis.
Mais maintenant que Facebook l’a racheté puis arrêté (à la surprise générale) j’ai cherché un service concurrent.

Les avantages de Parse (et sans doute d’autres) :

  • une SDK Javascript qui wrappe l’API Rest serveur built-in. Ca facilite les action CRUD
    et autres connectivités Oauth2. On y prend vite gout ^^
  • un outil CLI pour faciliter les déploiements, les rollbacks, log in console
  • des extensions (manip d’image, outil mailing, analytics, files)
  • Hosting : hébergement de l’appli frontend
  • Cloud Code : API Rest built-in + la possibilité de l’étendre avec ses propres fonctions métier (en NodeJS)
  • création d’ACL pour sécuriser les objets (tuples DB)
  • monitoring de trafic
  • un Data Studio pour créer ses modèles métier (modélisation base de données en gros)
  • 30 requêtes par IP par secondes, au dela c’est 100$ par mois.
  • push de données
  • stockage de fichiers en Cloud (Google ou CloudFront je sais plus)

Inconvénients :

  1. SDK JS basé sur Backbone. C’est pas incompatible avec Angular pour autant (tu cites Ionic)
    mais faut SURTOUT pas oublier d’invoquer $scope.$apply() dans les callbacks des méthode SDK qui font des appels Ajax.
    Sur Github ya des portages Angular de la SDK Parse, mais aucun n’a fonctionné chez moi.
  2. Les objets Backbone fonctionnent avec des get/set, alors que Angular fonctionne en dirty checking (object.prop)

Warning : L’isomorphisme :
…qui a des tonnes de vertus mais requiert des gros points de vigilance :
Autrefois on codait en JS pour le client-side, et en PHP (ou autre) pour le server-side. Les frontières étaient naturelles, pas d’ambiguité : le code JS est accessible, le code PHP ne l’est pas. Chacun son camp. Point.
Maintenant avec le codage full-JS, on change la donne, ces frontières n’existent plus. Le meme code marche aussi bien d’un coté que de l’autre. Il faut simplement penser différemment sinon on prend de mauvaises habitudes.

Dans les premières semaines, je me suis un peu fait peur : je me suis surpris à coder des choses sensibles (domaine métier) côté client.
Par exemple la création et l’édition d’un compte client.
Abérrant hein ?
"Ba oui mais ca fonctionne, la SDK et l’API Rest le permettent."
Et c’est là que même avec 10 d’expé, on se met à refaire des erreurs de débutants.
J’ai donc tôt fait de prendre l’habitude de me répéter 50 fois par jour :

  • “oui ca marche, mais est-ce que code est au bon endroit ?”
  • “est ce que craint si le code est accessible / lisible par n’importe qui” ?
  • “ai je besoin d’avoir la main/ contrôle / autorité sur ce code ?”
    –> ex : si j’ai besoin de désactiver un traitement métier, mais que la règle qui l’entoure évolue entretemps et l’invalide.

Autres services MBaaS :
Depuis, j’en ai testé d’autres qui m’ont +/- convaincu :

  • ApperyIO : pas accroché l’ergonomie UI
  • Backand : vraiment pas mal mais tout en appels Rest (or j’ai pris gout à la SDK JS)
  • Firebase : Data Studio mal foutu (trop orienté NoSQL pour moi)
  • Kinvey : mon préféré : ressemble beaucoup à Parse (un peu cher mais service à haute valeur)

J’ai pas essayé :
Modulus,
Kuzzle
BaasBox
DreamFactory
StrongLoop
BuiltIO
Buddy
Anypresence
Kumulos

Hésite pas à compléter la liste !

Pricing :
En général le Starter plan est gratuit. Puis si tu dépasses un plafond tu paies.
Soit un forfait mensuel soit du “pay as you go” qui est plus équitable.
J’ai pas étudié tous les modèle de pricing. Si tu as bien avancé sur ce sujet hésite pas a partager.

My two cents.

1 J'aime

Merci pour cette réponse très complète.

Effectivement, parse paraissait être une bonne solution. Cependant, il va fermer dans environ 1an…
De ce fait, je me suis finalement orienté vers Firebase que je trouve facile d’emploie (ça reste une question de goût).

Par contre, Firebase ne permet pas de stocker des image de grosse taille. Je recherche un service permettant l’upload d’image comme Cloudinary. Celui-ci n’est pas supporté par ionic.

Et je recherche également, un service permettant l’hébergement de mon appli web frontend.

(Sauf mauvaise compréhension de ma part)
Cloudinary pas supporté par Ionic ? Je pense que tu confond Ionic et ce qu’il “contient”.
En effet ya ce qu’il faut côté client : https://github.com/cloudinary/cloudinary_angular
Et l’API server-side est déclinée pour tous les goûts : NodeJS / RoR / .Net / PHP / Python, …

personnellement, je ne suis pas parvenue à l’utiliser. j’ai passé pas mal de temps à essayer. As-tu déjà réussi a utilisé l’API?

Je suis également tombé sur cette page : https://calendee.com/2015/01/15/posting-images-to-cloudinary-in-ionic-apps/

Mais j’ai l’erreur:
Error: [$injector:unpr] Unknown provider: $translateProvider <- $translate <- ImageUploadService

Dans le code d’exemple, $translate est une dépendance qui est injectée dans la fonction “ius” mais n’est jamais utilisée.
Supprime $translate dans function ius($q, $ionicLoading, $cordovaFile, $translate, CLOUDINARY_CONFIGS)

1 J'aime

Merci. J’ai plus cette erreur.

Par contre, lorsque que j’essaie d’upload une image avec cette fonction:

`'Use Strict';
angular.module('App').controller('editeventController', function ($scope,ImageUploadService) {


    $scope.upload = function () {
      
        ImageUploadService.uploadImage("img/test.jpg").then(  
        function (result) {

            var url = result.secure_url || '';
            var urlSmall;

            if (result && result.eager[0]) urlSmall = result.eager[0].secure_url || '';

            // Do something with the results here.

            $cordovaCamera.cleanup();

        },
        function (err) {

            // Do something with the error here
            $cordovaCamera.cleanup();

        });
      
    }

J’ai le message:

`TypeError: window.resolveLocalFileSystemURL is not a function
at Object.uploadImage (http://localhost:8100/js/services/utils.js:78:20)
at Scope.$scope.upload (http://localhost:8100/views/editevent/editevent.js:6:28)

Pbm connu manifestement, suite à un ptit tour sur Stack Overflow :

manque un plugin.

Tes dépendances (dont l’API Cloudinary) tu les as importé comment dans ton projet Ionic ?

J’ai d’abord essayer d’installer cloudinary comme sur le lien que tu m’as envoyé : https://github.com/cloudinary/cloudinary_angular

Mais j’avais pas mal d’erreur sur le script. Du coup je n’importe plus le script angular.cloudinary.js et j’ai suivi ce lien:

https://calendee.com/2015/01/15/posting-images-to-cloudinary-in-ionic-apps/

J’ai donc créer cette fonction dans mon utils.js:

(function () {
    function ius($q, $ionicLoading, $cordovaFile, $translate ) {  //CLOUDINARY_CONFIGS
        var service = {};
        service.uploadImage = uploadImage;
        return service;
        function uploadImage(imageURI) {
            var deferred = $q.defer();
            var fileSize;
            var percentage;
            // Find out how big the original file is
            window.resolveLocalFileSystemURL(imageURI, function (fileEntry) {
                fileEntry.file(function (fileObj) {
                    fileSize = fileObj.size;
                    // Display a loading indicator reporting the start of the upload
                    $ionicLoading.show({ template: 'Uploading Picture : ' + 0 + '%' });
                    // Trigger the upload
                    uploadFile();
                });
            });
            function uploadFile() {
                // Add the Cloudinary "upload preset" name to the headers
                var uploadOptions = {
                    params: { 'upload_preset': CLOUDINARY_CONFIGS.UPLOAD_PRESET }  //CLOUDINARY_CONFIGS.UPLOAD_PRESET
                };
                $cordovaFile
                  // Your Cloudinary URL will go here
                  .uploadFile(CLOUDINARY_CONFIGS.API_URL, imageURI, uploadOptions)  //

                  .then(function (result) {
                      // Let the user know the upload is completed
                      $ionicLoading.show({ template: 'Upload Completed', duration: 1000 });
                      // Result has a "response" property that is escaped
                      // FYI: The result will also have URLs for any new images generated with 
                      // eager transformations
                      var response = JSON.parse(decodeURIComponent(result.response));
                      deferred.resolve(response);
                  }, function (err) {
                      // Uh oh!
                      $ionicLoading.show({ template: 'Upload Failed', duration: 3000 });
                      deferred.reject(err);
                  }, function (progress) {
                      // The upload plugin gives you information about how much data has been transferred 
                      // on some interval.  Use this with the original file size to show a progress indicator.
                      percentage = Math.floor(progress.loaded / fileSize * 100);
                      $ionicLoading.show({ template: 'Uploading Picture : ' + percentage + '%' });
                  });
            }
            return deferred.promise;
        }
    }
    angular.module('App').factory('ImageUploadService', ius);
})();

Le mieux serait peut être de reprendre depuis le début, et de me dire étape par étape comment importer les dépendances?

Si ça peut t’aider voici mon index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title>Exeo</title>


    <!-- compiled css output -->
    <link href="css/ionic.app.css" rel="stylesheet"> 
    <link href="css/style.css" rel="stylesheet">

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
      <script src="lib/ngCordova/dist/ng-cordova.min.js"></script>
    <script src="cordova.js"></script>

    <!--       your app's js -->
    <script src="js/app.js"></script>
    <script src="js/controllers.js"></script>
    <script src="views/register/register.js"></script>
    <script src="js/services/auth.js"></script>
      <script src="js/services/utils.js"></script>

      <script src="bower_components/ionic-datepicker/dist/ionic-datepicker.bundle.min.js"></script>
      <script src="bower_components/ionic-timepicker/dist/ionic-timepicker.bundle.min.js"></script>
     <!--  <script src="bower_components/cloudinary-core/cloudinary-core.js"></script>
      <script src="bower_components/cloudinary_ng/js/angular.cloudinary.js"></script>
     <!--   <script src="bower_components/ng-file-upload/ng-file-upload-shim.js"></script>
      <script src="bower_components/ng-file-upload/ng-file-upload.js"></script> -->

    <!-- libraries  -->
    <script src="lib/ngstorage/ngStorage.min.js"></script>
    <script src="lib/firebase/firebase.js"></script>
   <script src="lib/angularfire/dist/angularfire.min.js"></script>
    <script src="lib/angular-messages/angular-messages.min.js"></script>

  </head>
  <body ng-app="App">
      <ion-nav-view></ion-nav-view>
  </body>
</html>

Quid d’une appli Rails en mode API only ?
http://edgeguides.rubyonrails.org/api_app.html

1 J'aime

Tu veux dire à la place d’un MBaaS ?

Oui, le sujet du post étant “Quel backend pour une application Ionic”.

Un backend en Rails (mode API only, ou pas d’ailleurs) peut aller vite et te permettra d’être souple sur tes évols.
De plus il y a forcément des gems qui permettent d’avoir les statistiques et analytics que tu apprécies chez MBaaS.