MontageJS

 


INTRODUCTION 

MontageJS framework (ou Montage) est une plateforme permettant de développer et créer facilement des applications « single page » (qui chargent de simples page HTML et mettent à jour dynamiquement l’application lorsque l’utilisateur interagit avec la page).

Son but est de simplifier le développement et la maintenabilité des applications HTML5. MontageJS fournit des composants modulaires, une liaison bidirectionnelle en temps réel, la sérialisation des objets avec le mappage DOM, la gestion des évènements, un cycle de dessin de composants gérés, la gestion des dépendances CommonJS et bien d’autres applications web, pour garantir une expérience utilisateur fluide, en particulier sur les périphériques à ressources limitées.

 


CONTEXTE 

Le développement de MontageJS a débuté avec Benoit Marchant et son équipe chez Motorola Mobility, de Août 2010 à Juillet 2012. Le projet a été ouvert sur GitHub en Juillet 2012 sous licence BSD. Le framework MontageJS est actuellement géré par une start-up de la Silicon Valley dont les employés incluent Benoit Marchant et les principaux membres de son équipe d’origine.

Les idées derrière ce framework remontent à l’époque lorsque Benoit Marchant était employé chez Apple (1999 – 2010), où il travaillait sur des interfaces utilisateurs natives écrites en JavaScript. Son objectif était de créer l’équivalent de technologies telles que Cocoa et WebObjects mais pour le web et côté client, faciliter le développement d’applications HTML, CSS et JavaScript. Le résultat était Gianduia, un framework riche introduit par Apple lors de la World of WebObjects Developer Confererence en 2009.

En 2010, lorsque Benoit Marchant a eu l’opportunité de rejoindre Motorola Mobility pour travailler sur un nouveau framework pour mobile, grâce à son expérience chez Apple, il a su construire Montage à partir de rien en s’appuyant sur le modèle MVC (Model-View-Controller).  Bien que le framework soit toujours en train d’évoluer, avec beaucoup plus de composants, Montage a été utilisé pour développer des applications prêtes pour la production.

Montage diffère de ces prédécesseurs, comme Cappuccino, car il n’essaie pas d’introduire de nouvelles syntaxes pour le web. Il utilise une API ressemblant à Cocoa pour créer une couche d’abstraction propre au-dessus de la web stack en utilisant des composants modulaires et autonomes, des objets réels et des collections, et une API permettant d’observer les changements sur ces objets et leurs propriétés ou collections.

 

Benoit Marchant lors de la JSConfUY (JavaScript Conference in Uruguay) en 2014


SPÉCIFICITÉS

[COMPOSANTS ENCAPSULÉS]

MontageJS dispose d’une interface propre pour créer des composants d’interface utilisateur personnalisés. Chaque composant peut être autonome ou être composé d’autres composants. Chaque composant est modélisé en tant qu’application Web autonome avec son propre modèle HTML, CSS, JavaScript, son modèle d’objet de composant sérialisé et ses ressources. À quelques exceptions près, un composant peut se tenir sur la plate-forme Web comme n’importe quelle autre page Web. Il n’y a pas de modèles entièrement JavaScript dans MontageJS. Cette séparation des préoccupations permet aux conceptions d’utiliser les technologies avec lesquelles ils sont à l’aise (sans avoir à creuser dans le JavaScript) et les développeurs pour isoler et tester des composants individuels en utilisant des techniques familières.

[LIAISON DÉCLARATIVE DE DONNÉES]

MontageJS facilite la gestion de l’application et de l’état de l’interface utilisateur avec les liaisons de données. Un composant UI ou un objet MontageJS peut établir une liaison simple ou bidirectionnelle avec un autre composant ou objet. Lorsque la propriété liée est mise à jour, l’objet source est conservé en synchronisation.

MontageJS utilise des liaisons réactives fonctionnelles (FRB, functional reactive bindings). Contrairement aux liaisons traditionnelles, FRB peut lier avec élégance les longs chemins de propriété et le contenu des collections. Ils peuvent également mettre à jour de manière incrémentielle les résultats des chaînes de requêtes, y compris les maps, les tableaux, les sommes et les moyennes ainsi qu’ajouter et supprimer des éléments des sets en fonction des modifications apportées sur un indicateur. FRB permet d’assurer la progression vers un état cohérent.

[COMMONJS]

MontageJS prend entièrement en charge les modules CommonJS et fait partie de l’écosystème des paquets Node et npm.

 


INSTALLATION

[REQUIREMENTS]
  • Node.js et npm
  • Un navigateur stable (Chrome, Safari, Firefox)
  • Pour contribuer, un client git and une clé SSH publique
[SETUP]
  • Téléchargez et exécuter le programme d’installation js prédéfini pour votre plateforme : https://nodejs.org/download/
  • Installez minit pour initialiser MontageJS

Minit est une commande qui vous aidera à démarrer votre projet MontageJS en générant des modèles et composants d’application MontageJS prédéfinis et en plaçant les fichiers associés dans les répertoires appropriés de votre projet.

 

Mac OS X / Linux

$ mkdir -p ~/.npm
$ sudo npm install -gq minit@latest

Windows

Lancez l’invite de commande Node.js

$ npm install -gq minit@latest

  • Utilisez minit pour créer le projet MontageJS
$ minit create:app -n yourappname

NOTE : Si vous obtenez le warning EACCES lorsque vous essayez d’exécuter minit: create, utilisez :

$ sudo chown –R <nom utilisateur> ~/.npm
$ minit create: app –n yourappname

Ceci génère un nouveau dossier intitulé yourappname, qui contient un template MontageJS par défaut, y compris les dépendances de productions, dans votre répertoire courant.

 

  • Pour vérifier l’installation et lancer le projet :
    $ cd yourappname
    $ minit serve &
  • Allez sur votre navigateur et tapez l’url : http://localhost:8083

Vous devriez alors arriver sur la page suivante :

 

 


 

PROJET MONTAGEJS

Nous avons vu dans la partie précédente comment générer un projet MontageJS grâce aux lignes de commandes.

Lorsque nous ouvrons le projet dans un éditeur de texte ou IDE, nous obtenons une hiérarchie comme celle-ci.

Actuellement, il est possible d’accéder au beta de Montage Studio, l’IDE développé par Kaazing pour développer avec le Framework MontageJS. Pour cela, il suffit de remplir le formulaire suivant : http://montagestudio.com/reveal/.

 

 

 


BASIQUES

Le développement d’une application MontageJS est partagée en deux : une phase de développement (assemblage de l’application) et sa phase de production (optimisation de l’application pour le déploiement). En développement, vous assemblez une application à partir de composants encapsulés. Ces composants sont stockés dans le répertoire ui  de votre projet et identifiés par un suffixe .reel.

 

 

Dans la hiérarchie du projet :

  • montage-example correspond au template du projet
  • node_modules contient les dépendances du code pour le développement
  • ui contient les composants de l’interface utilisateur encapsulés et chacun de ces derniers est composé de trois fichiers qui contrôlent sa structure (HTML), l’apparence (CSS) et son comportement (JS).

main.reel est le composant principale de l’interface utilisateur de l’application. Considérez-le comme l’équivalent MontageJS de la page index.html d’un site web. Il peut contenir un nombre quelconque de sous-composants. Le composant converter encapsule la fonctionnalité de l’application. Le composant version a pour seul but de vous informer de la version de MontageJS qui est utilisée.

Il est tout à fait possible de concevoir une application complète en utilisant uniquement le composant Main, cependant, il est fortement recommandé d’assembler les applications MontageJS à partir de composants individuels (comme construire un site web à partir de pages individuelles) pour obtenir une architecture modulaire et des composants encapsulés et réutilisables.

 


EXEMPLE

À titre d’exemple, nous allons créer un composant Convertisseur de température :

 

  • Créer un nouveau projet MontageJS : temp-converter
$ minit create:app -n temp-converter

  • Lancer l’application :
$ cd temp-converter
$ minit serve &

À ce stade, nous obtenons seulement une page blanche avec la version utilisée de MontageJS.

 

  • Nous allons alors créer un composant :
$ minit create:component -n converter
 

Cette ligne de commande place un nouveau composant, converter.reel dans le repertoire ui de votre projet. Pour l’incorporer dans votre application, vous devez le déclarer dans le composant principal.

 

  • Ouvrez le fichier ui/main.reel/main.html
  • Entre les balises <body>, avant <div data-montage-id="montageVersion"> </div> ajoutez :
<h1>Temperature Converter</h1>
<div data-montage-id="tempConverter"></div>

L’attribut data-montage-id est utilisé pour identifier les éléments du balisage dont vous voulez contrôler le comportement. Les objets qui contrôlent ces éléments sont situés dans le bloc script du header du document HTML.

 

  • Entre les balises <script> du header, après l’objet owner :
"tempConverter": {
       "prototype": "ui/converter.reel",
       "properties": {
            "element": {"#": "tempConverter"}
        }
},

Ceci déclare une instance du composant Converter avec un label d’objet de tempConverter. Sa propriété element correspond à l’élément HTML associé que vous avez ajouté à l’étape précédente.

Après avoir sauvegardé les modifications et rafraichi la page vous devez obtenir :

 



L’application que nous souhaitons construire est composée de quatre éléments : un titre, deux champs de saisie numérique et un slider, qui doivent être déclarés dans nos balises. Nous avons déjà déclaré le titre de l’application dans main.html. Nous allons par la suite utiliser le fichier converter.html.

 

  • Ouvrez le fichier ui/converter.reel/converter.html
  • Remplacez le code HTML entre les balises <div> par :
<fieldset>
       <div>&deg;C
             <input type="number"/>
       </div>
       <div>&deg;F
             <input type="number"/>
       </div>
</fieldset>
<fieldset>
       <input type="range"/>
</fieldset> 

 

  • On devrait obtenir le résultat suivant :

 

Définition du template

  • Dans ui/converter.reel/converter.html, entre le parent <div data-montage-id="owner" class="Converter">:

    <fieldset>
        <div>&deg;C
           <input data-montage-id="celsius"/>
        </div>
        <div>&deg;F
           <input data-montage-id="fahrenheit"/>
        </div>
    </fieldset>
    <fieldset>
       <input data-montage-id="thermometer" type="range" />
    </fieldset>


Ajoutez les composants qui contrôlent ces éléments HTML :

  • Entre les balises <script>, ajoutez trois objets json sérialisés :  
    {
        "owner": {
            "properties": {
                "element": {"#": "owner"}
            }
        },
         "celsiusNumberfield": {
            "prototype": "digit/ui/number-field.reel",
            "properties": {
                "element": {"#": "celsius"}
             }
        },
         "fahrenheitNumberfield": {
            "prototype": "digit/ui/number-field.reel",
            "properties": {
                "element": {"#": "fahrenheit"}
            }
        },
         "thermometer": {
            "prototype": "digit/ui/slider.reel",
            "properties": {
                "element": {"#": "thermometer"},
                "axis": "vertical"
            }
        }
    }

 


Explications :

  • Les libellés celsiusNumberfield, fahrenheitNumberfield et thermometer identifient les objets sérialisés qui contrôlent le comportement des éléments HTML correspondants
  • prototype identifie le répertoire qui contient le code du prototype de cet objet (ici, on utilise des composants de l’ensemble de widgets Digit optimisé pour la plateforme mobile, faisant parti du projet MontageJS par défaut)
  • properties liste les valeurs assignées aux propriétés de l’objet courant
  • element correspond aux éléments du DOM qu’on souhaite contrôler, identifiés data-montage-id de celsius, fahrenheit et thermometer
  • axis remplace le slider horizontal par un slider vertical 

     

     

    En rafraichissant la page, on doit obtenir le résultat suivant :

 

 

 

Ajout des bindings

 

MontageJS utilise les functional reactive bindings (FRB), qui sont déclarés dans les objets que l’on souhaite bindé ensemble.

  • Remplacez le contenu de <script> avec :
    {
        "owner": {
            "properties": {
                "element": {"#": "owner"}
            }
        },
         "celsiusNumberfield": {
            "prototype": "digit/ui/number-field.reel",
            "properties": {
                "element": {"#": "celsius"}
            },
            "bindings": {
                "value": {"<->": "(+@fahrenheitNumberfield.value - 32) / 1.8"}
            }
        },
         "fahrenheitNumberfield": {
            "prototype": "digit/ui/number-field.reel",
            "properties": {
                "element": {"#": "fahrenheit"},
                "value": "32"
            }
        },
         "thermometer": {
            "prototype": "digit/ui/slider.reel",
            "properties": {
                "element": {"#": "thermometer"},
                "axis": "vertical"
            },
            "bindings": {
                "value": {"<->": "@fahrenheitNumberfield.value"}
            }
        }
    }

 

Couche de peinture

 

  • Dans ui/converter.reel/converter.html ajoutez :
<fieldset class="Numbers">
            <div class="Label">&deg;C
               <input data-montage-id="celsius">
            </div>
            <div class="Label">&deg;F
               <input data-montage-id="fahrenheit">
            </div>
</fieldset>
<fieldset class="Slider">
       <input data-montage-id="thermometer" class="Slider-handle" type="range" min="-13" max="122">
</fieldset>


  • Modifions la partie CSS, dans ui/converter.reel/converter.css

 

     .Converter {
        margin: 20px auto;
        padding: 20px;
        width: 300px;
        border-radius: 10px;
        background-color: hsl(0,0%,98%);
        box-shadow: inset 0px 1px 2px 1px hsla(0,0%,100%,1), 0px 2px 5px hsla(0,0%,0%,.1);
    }
     .Converter:after {
        content: "";
        display: block;
        clear: both;
    }
     .Numbers {
        float: left;
        border: none;
        margin: 0;
        padding: 0;
    }
     .Label {
        margin: 15px 0;
        line-height: 40px;
        font-size: 1.2em;
    }
     .Label .digit-NumberField-input {
        width: 70px;
        vertical-align: middle;
    }
     .Slider {
        float: right;
        margin: 0;
        padding: 8px 4px;
        border-radius: 100px;
        border: none;
        box-shadow: inset 0px 1px 3px hsla(0,0%,0%,.3),
                    0 2px 0 hsla(0,0%,100%,1);
        background: -webkit-linear-gradient(bottom,
                    hsl(200,100%,50%),
                    hsl(200,100%,80%) 30%,
                    hsl(60,100%,65%) 50%,
                    hsl(0,100%,80%) 70%,
                    hsl(0,100%,50%) );
        background: linear-gradient(to top,
                    hsl(200,100%,50%),
                    hsl(200,100%,80%) 30%,
                    hsl(60,100%,65%) 50%,
                    hsl(0,100%,80%) 70%,
                    hsl(0,100%,50%) );
    }
     .Slider-handle.digit-Slider.montage-Slider--vertical {
        height: 120px;
    }
     .Slider-handle.digit-Slider {
        background-color: transparent;
        border-color: transparent;
        box-shadow: none;
    }

Arrivé à ce stade-là, le résultat doit ressembler à ceci :

 





Design du composant principal

 

  • Dans ui/main.reel/main.html, remplacez le contenu de <div data-montage-id="main" data-montage-skin="light" class="Main"> par :
    <h1 data-montage-id="title" class="Title"></h1>
    <div data-montage-id="tempConverter"></div>
    <footer data-montage-id="montageVersion"></footer>

 

  • À la suite de l’objet tempCoverter dans les balises <script> ajoutez :
    "title": {
        "prototype": "digit/ui/title.reel",
        "properties": {
            "element": {"#": "title"},
            "value": "Temperature Converter"
        }
    },

Ceci declare une instance du composant Title et définit la valeur de l’élément h1 à Temperature Converter.

 

  • Dans ui/main.reel/main.css remplacez le contenu existant par :
  * {
        -moz-box-sizing: border-box;
        box-sizing: border-box;
    }
     body {
        margin: 0;
        font-family: "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
        color: hsl(0,0%,60%);
        background-color: hsl(0,0%,95%);
    }
    .Main {
        padding: 3em 1em;
        text-align: center;
    }
     .Title {
        font-size: 1.3em;
    }

Le résultat final est donc :

 

 

Le déploiement

 

Comme indiqué précédemment, la construction d’applications MontageJS est divisée en deux phases : le développement et la production. Lorsque votre application est terminée, vous devez la préparer pour le déploiement. C’est ici qu’intervient mop, l’optimiseur de MontageJS.

Mop est un outil de ligne de commande simple qui transforme une application en développement en une application optimisée prête pour le déploiement. Dans le processus, mop minimise également votre code pour accélérer le chargement de l’application.

 

  • Mop ne fait pas partie du projet de démarrage par défaut de MontageJS, vous devez alors l’installer séparément :
$ sudo npm install –g mop

  • Allez dans le répertoire de votre projet :
$ cd temp-converter
$ mop

Mop va analyser les dépendances du code, identifier les modules utilisés par l’application, puis ajoute un répertoire builds à votre répertoire de projet contenant une version réduite de votre application.

 

 


MORE...

 

 

 

 

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *