Créez des échafaudages pour vos applications Web avec des outils modernes
Introduction
Allo' Allo'. Toute personne qui écrit une application Web sait à quel point il est important de rester productif. Il est difficile de s'occuper de tâches fastidieuses comme trouver le modèle approprié, configurer un workflow de développement et de test, et minifier et compresser toutes vos sources.
Heureusement, les outils de front-end modernes peuvent vous aider à automatiser une grande partie de ces tâches, ce qui vous permet de vous concentrer sur la création d'une application de qualité. Cet article vous explique comment utiliser Yeoman, un workflow d'outils pour les applications Web qui permet de simplifier la création d'applications à l'aide de Polymer, une bibliothèque de polyfills et de sucre pour le développement d'applications à l'aide de composants Web.
Découvrez Yo, Grunt et Bower
Yeoman est un homme portant un chapeau et qui propose trois outils pour améliorer votre productivité:
- yo est un outil d'échafaudage qui propose un écosystème d'échafaudages spécifiques au framework, appelés générateurs, qui peuvent être utilisés pour effectuer certaines des tâches fastidieuses que j'ai mentionnées précédemment.
- grunt permet de compiler, d'afficher un aperçu et de tester votre projet, grâce aux tâches sélectionnées par l'équipe Yeoman et grunt-contrib.
- bower est utilisé pour la gestion des dépendances, ce qui vous évite de télécharger et de gérer manuellement vos scripts.
Avec une ou deux commandes, Yeoman peut écrire du code standard pour votre application (ou des éléments individuels tels que des modèles), compiler votre Sass, réduire et concaténer vos fichiers CSS, JS, HTML et images, et démarrer un serveur Web simple dans votre répertoire actuel. Il peut également exécuter vos tests unitaires et plus encore.
Vous pouvez installer des générateurs à partir de Node Packaged Modules (npm). Plus de 220 générateurs sont désormais disponibles, dont beaucoup ont été écrits par la communauté Open Source. Parmi les générateurs populaires, citons generator-angular, generator-backbone et generator-ember.
Une fois une version récente de Node.js installée, accédez au terminal le plus proche et exécutez la commande suivante:
$ npm install -g yo
Et voilà ! Vous disposez désormais de Yo, Grunt et Bower, et vous pouvez les exécuter directement à partir de la ligne de commande. Voici la sortie de l'exécution de yo
:
Générateur de polymères
Comme indiqué précédemment, Polymer est une bibliothèque de polyfills et de sucre qui permet d'utiliser les composants Web dans les navigateurs modernes. Ce projet permet aux développeurs de créer des applications à l'aide de la plate-forme de demain et d'informer le W3C des points où les spécifications en vol peuvent être améliorées.
generator-polymer est un nouveau générateur qui vous aide à créer des applications Polymer à l'aide de Yeoman. Il vous permet de créer et de personnaliser facilement des éléments Polymer (personnalisés) via la ligne de commande, et de les importer à l'aide d'importations HTML. Vous gagnez ainsi du temps, car le code de base est écrit pour vous.
Installez ensuite le générateur de Polymer en exécutant la commande suivante:
$ npm install generator-polymer -g
Et voilà ! Votre application dispose désormais des super-pouvoirs des composants Web.
Notre nouveau générateur comporte quelques éléments spécifiques auxquels vous aurez accès:
polymer:element
permet de créer des échafaudages pour de nouveaux éléments Polymer individuels. Par exemple :yo polymer:element carousel
polymer:app
permet de créer une structure pour votre fichier index.html initial, un fichier Gruntfile.js contenant la configuration au moment de la compilation de votre projet, ainsi que des tâches Grunt et une structure de dossiers recommandée pour le projet. Vous pourrez également utiliser Sass Bootstrap pour les styles de votre projet.
Créer une application Polymer
Nous allons créer un blog simple à l'aide d'éléments Polymer personnalisés et de notre nouveau générateur.
Pour commencer, accédez au terminal, créez un répertoire et accédez-y à l'aide de mkdir my-new-project && cd $_
. Vous pouvez maintenant lancer votre application Polymer en exécutant:
$ yo polymer
Vous obtenez ainsi la dernière version de Polymer à partir de Bower, et vous créez une structure de répertoires, un fichier index.html et des tâches Grunt pour votre workflow. Pourquoi ne pas prendre un café pendant que l'application se prépare ?
Nous pouvons maintenant exécuter grunt server
pour avoir un aperçu de l'application:
Le serveur est compatible avec LiveReload. Vous pouvez donc lancer un éditeur de texte, modifier un élément personnalisé, et le navigateur se rechargera à l'enregistrement. Vous obtenez ainsi une vue en temps réel de l'état actuel de votre application.
Créons ensuite un élément Polymer pour représenter un article de blog.
$ yo polymer:element post
Yeoman nous pose quelques questions, par exemple si nous souhaitons inclure un constructeur ou utiliser une importation HTML pour inclure l'élément post dans index.html
. Pour l'instant, répondons "Non" aux deux premières options et laissons la troisième vide.
$ yo polymer:element post
[?] Would you like to include constructor=''? No
[?] Import to your index.html using HTML imports? No
[?] Import other elements into this one? (e.g 'another_element.html' or leave blank)
create app/elements/post.html
Un élément Polymer nommé post.html est créé dans le répertoire /elements
:
<polymer-element name="post-element" attributes="">
<template>
<style>
@host { :scope {display: block;} }
</style>
<span>I'm <b>post-element</b>. This is my Shadow DOM.</span>
</template>
<script>
Polymer('post-element', {
//applyAuthorStyles: true,
//resetStyleInheritance: true,
created: function() { },
enteredView: function() { },
leftView: function() { },
attributeChanged: function(attrName, oldVal, newVal) { }
});
</script>
</polymer-element>
Il comprend :
- Code standard pour votre élément personnalisé, qui vous permet d'utiliser un type d'élément DOM personnalisé sur votre page (par exemple,
<post-element>
) - Une balise de modèle pour la création de modèles côté client "natifs" et des exemples de styles de portée pour encapsuler les styles de votre élément
- Modèle de registre d'éléments et événements de cycle de vie.
Travailler avec une source de données réelle
Notre blog aura besoin d'un endroit où écrire et lire les nouveaux articles. Pour illustrer l'utilisation d'un véritable service de données, nous allons utiliser l'API Google Apps Sheets. Cela nous permet de lire facilement le contenu de n'importe quelle feuille de calcul créée avec Google Docs.
Pour configurer cette fonctionnalité:
Dans votre navigateur (Chrome est recommandé), ouvrez cette feuille de calcul Google Docs. Il contient des exemples de données de post dans les champs suivants:
- ID
- Titre
- Auteur
- Contenu
- Date
- Mots clés
- Adresse e-mail (de l'auteur)
- Libellé (pour l'URL du libellé de votre post)
Accédez au menu Fichier, puis sélectionnez Créer une copie pour créer votre propre copie de la feuille de calcul. Vous pouvez modifier le contenu à votre guise, en ajoutant ou en supprimant des posts.
Accédez à nouveau au menu Fichier, puis sélectionnez Publier sur le Web.
Cliquez sur Start publishing (Démarrer la publication).
Sous Obtenir un lien vers les données publiées, dans la dernière zone de texte, copiez la partie clé de l'URL fournie. Elle se présente comme suit: https://docs.google.com/spreadsheet/ccc?key=0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc#gid=0.
Collez la clé à la place de votre-clé-ici dans l'URL suivante: https://spreadsheets.google.com/feeds/list/your-key-goes-here/od6/public/values?alt=json-in-script&callback=. Par exemple, si vous utilisez la clé ci-dessus, l'URL peut ressembler à https://spreadsheets.google.com/feeds/list/0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc/od6/public/values?alt=json-in-script.
Vous pouvez coller l'URL dans votre navigateur et y accéder pour afficher la version JSON du contenu de votre blog. Notez l'URL, puis prenez le temps d'examiner le format de ces données, car vous devrez les itérer pour les afficher à l'écran plus tard.
La sortie JSON dans votre navigateur peut sembler un peu intimidante, mais ne vous inquiétez pas. Nous ne sommes intéressés que par les données de vos posts.
L'API Google Sheets affiche chacun des champs de votre feuille de calcul de blog avec un préfixe spécial post.gsx$
. (par exemple, post.gsx$title.$t
, post.gsx$author.$t
, post.gsx$content.$t
, etc.) Lorsque nous itérerons sur chaque "ligne" de notre sortie JSON, nous ferons référence à ces champs pour récupérer les valeurs pertinentes pour chaque post.
Vous pouvez désormais modifier l'élément de post nouvellement mis en échafaudage pour lier des parties de balisage aux données de votre feuille de calcul. Pour ce faire, nous introduisons un attribut post
, qui lira le titre, l'auteur, le contenu et d'autres champs que nous avons créés précédemment. L'attribut selected
(que nous remplirons ultérieurement) permet d'afficher un post uniquement si un utilisateur accède au slug correspondant.
<polymer-element name="post-element" attributes="post selected">
<template>
<style>
@host { :scope {display: block;} }
</style>
<div class="col-lg-4">
<template if="[[post.gsx$slug.$t === selected]]">
<h2>
<a href="#[[post.gsx$slug.$t]]">
[[post.gsx$title.$t ]]
</a>
</h2>
<p>By [[post.gsx$author.$t]]</p>
<p>[[post.gsx$content.$t]]</p>
<p>Published on: [[post.gsx$date.$t]]</p>
<small>Keywords: [[post.gsx$keywords.$t]]</small>
</template>
</div>
</template>
<script>
Polymer('post-element', {
created: function() { },
enteredView: function() { },
leftView: function() { },
attributeChanged: function(attrName, oldVal, newVal) { }
});
</script>
</polymer-element>
Créons ensuite un élément de blog contenant à la fois une collection d'articles et la mise en page de votre blog en exécutant yo polymer:element blog
.
$ yo polymer:element blog
[?] Would you like to include constructor=''? No
[?] Import to your index.html using HTML imports? Yes
[?] Import other elements into this one? (e.g 'another_element.html' or leave blank) post.html
create app/elements/blog.html
Cette fois, nous importons le blog dans index.html à l'aide d'importations HTML, comme nous le souhaitons qu'il apparaisse sur la page. Pour la troisième requête, nous spécifions post.html
comme élément à inclure.
Comme précédemment, un nouveau fichier d'élément (blog.html) est créé et ajouté à /elements. Cette fois, le fichier post.html est importé et <post-element>
est inclus dans la balise de modèle:
<link rel="import" href="post.html">
<polymer-element name="blog-element" attributes="">
<template>
<style>
@host { :scope {display: block;} }
</style>
<span>I'm <b>blog-element</b>. This is my Shadow DOM.</span>
<post-element></post-element>
</template>
<script>
Polymer('blog-element', {
//applyAuthorStyles: true,
//resetStyleInheritance: true,
created: function() { },
enteredView: function() { },
leftView: function() { },
attributeChanged: function(attrName, oldVal, newVal) { }
});
</script>
</polymer-element>
Comme nous avons demandé que l'élément de blog soit importé dans notre index à l'aide d'importations HTML (un moyen d'inclure et de réutiliser des documents HTML dans d'autres documents HTML), nous pouvons également vérifier qu'il a été correctement ajouté au document <head>
:
<!doctype html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="styles/main.css">
<!-- build:js scripts/vendor/modernizr.js -->
<script src="bower_components/modernizr/modernizr.js"></script>
<!-- endbuild -->
<!-- Place your HTML imports here -->
<link rel="import" href="elements/blog.html">
</head>
<body>
<div class="container">
<div class="hero-unit" style="width:90%">
<blog-element></blog-element>
</div>
</div>
<script>
document.addEventListener('WebComponentsReady', function() {
// Perform some behaviour
});
</script>
<!-- build:js scripts/vendor.js -->
<script src="bower_components/polymer/polymer.min.js"></script>
<!-- endbuild -->
</body>
</html>
Magnifique.
Ajouter des dépendances à l'aide de Bower
Modifions ensuite notre élément pour utiliser l'élément utilitaire Polymer JSONP afin de lire posts.json. Vous pouvez obtenir l'adaptateur en clonant le dépôt git ou en installant polymer-elements
via Bower en exécutant bower install polymer-elements
.
Une fois que vous avez l'utilitaire, vous devez l'inclure en tant qu'importation dans l'élément blog.html avec:
<link rel="import" href="../bower_components/polymer-jsonp/polymer-jsonp.html">
Ensuite, incluez la balise correspondante et fournissez url
à la feuille de calcul des articles de blog que vous avez créée précédemment, en ajoutant &callback=
à la fin:
<polymer-jsonp auto url="https://spreadsheets.google.com/feeds/list/your-key-value/od6/public/values?alt=json-in-script&callback=" response="[[posts]]"></polymer-jsonp>
Nous pouvons maintenant ajouter des modèles pour itérer sur notre feuille de calcul une fois qu'elle a été lue. Le premier affiche un sommaire, avec un titre associé à un post qui pointe vers son slug.
<!-- Table of contents -->
<ul>
<template repeat="[[post in posts.feed.entry]]">
<li><a href="#[[post.gsx$slug.$t]]">[[post.gsx$title.$t]]</a></li>
</template>
</ul>
Le second affiche une instance de post-element
pour chaque entrée trouvée, en transmettant le contenu du post en conséquence. Notez que nous transmettons un attribut post
représentant le contenu du post pour une seule ligne de la feuille de calcul et un attribut selected
que nous allons renseigner avec un itinéraire.
<!-- Post content -->
<template repeat="[[post in posts.feed.entry]]">
<post-element post="[[post]]" selected="[[route]]"></post-element>
</template>
L'attribut repeat
utilisé dans notre modèle crée et gère une instance avec [[ bindings ]] pour chaque élément de la collection de tableaux de nos posts, lorsqu'il est fourni.
Pour que [[route]] soit renseigné, nous allons tricher et utiliser une bibliothèque appelée Flatiron Director, qui se lie à [[route]] chaque fois que le hachage de l'URL change.
Heureusement, il existe un élément Polymer (qui fait partie du package more-elements) que nous pouvons utiliser. Une fois copié dans le répertoire /elements, nous pouvons y faire référence avec <flatiron-director route="[[route]]" autoHash></flatiron-director>
, en spécifiant route
comme propriété à laquelle nous souhaitons associer et en lui demandant de lire automatiquement la valeur de toute modification de hachage (autoHash).
En rassemblant toutes les informations, nous obtenons:
<link rel="import" href="post.html">
<link rel="import" href="polymer-jsonp/polymer-jsonp.html">
<link rel="import" href="flatiron-director/flatiron-director.html">
<polymer-element name="blog-element" attributes="">
<template>
<style>
@host { :scope {display: block;} }
</style>
<div class="row">
<h1><a href="/#">My Polymer Blog</a></h1>
<flatiron-director route="[[route]]" autoHash></flatiron-director>
<h2>Posts</h2>
<!-- Table of contents -->
<ul>
<template repeat="[[post in posts.feed.entry]]">
<li><a href="#[[post.gsx$slug.$t]]">[[post.gsx$title.$t]]</a></li>
</template>
</ul>
<!-- Post content -->
<template repeat="[[post in posts.feed.entry]]">
<post-element post="[[post]]" selected="[[route]]"></post-element>
</template>
</div>
<polymer-jsonp auto url="https://spreadsheets.google.com/feeds/list/0AhcraNy3sgspdHVQUGd2M2Q0MEZnRms3c3dDQWQ3V1E/od6/public/values?alt=json-in-script&callback=" response="[[posts]]"></polymer-jsonp>
</template>
<script>
Polymer('blog-element', {
created: function() {},
enteredView: function() { },
leftView: function() { },
attributeChanged: function(attrName, oldVal, newVal) { }
});
</script>
</polymer-element>
Bravo ! Nous disposons désormais d'un blog simple qui lit des données à partir de JSON et utilise deux éléments Polymer mis en place avec Yeoman.
Utiliser des éléments tiers
L'écosystème d'éléments autour des composants Web a récemment connu une croissance, avec l'apparition de sites de galerie de composants comme customelements.io. En parcourant les éléments créés par la communauté, j'en ai trouvé un permettant d'extraire des profils Gravatar. Nous pouvons également les récupérer et les ajouter à notre site de blog.
Copiez les sources des éléments gravatar dans votre répertoire /elements
, incluez-les via des importations HTML dans post.html, puis ajoutez
<link rel="import" href="gravatar-element/src/gravatar.html">
<polymer-element name="post-element" attributes="post selected">
<template>
<style>
@host { :scope {display: block;} }
</style>
<div class="col-lg-4">
<template if="[[post.gsx$slug.$t === selected]]">
<h2><a href="#[[post.gsx$slug.$t]]">[[post.gsx$title.$t]]</a></h2>
<p>By [[post.gsx$author.$t]]</p>
<gravatar-element username="[[post.gsx$email.$t]]" size="100"></gravatar-element>
<p>[[post.gsx$content.$t]]</p>
<p>[[post.gsx$date.$t]]</p>
<small>Keywords: [[post.gsx$keywords.$t]]</small>
</template>
</div>
</template>
<script>
Polymer('post-element', {
created: function() { },
enteredView: function() { },
leftView: function() { },
attributeChanged: function(attrName, oldVal, newVal) { }
});
</script>
</polymer-element>
Voyons ce que cela nous donne:
Vraiment ?
En un temps relativement court, nous avons créé une application simple composée de plusieurs composants Web, sans avoir à écrire de code standard, à télécharger manuellement des dépendances ni à configurer un serveur local ou un workflow de compilation.
Optimisez votre application
Le workflow Yeoman inclut un autre projet Open Source appelé Grunt, un outil de gestion des tâches qui peut exécuter un certain nombre de tâches spécifiques au build (définies dans un fichier Gruntfile) pour produire une version optimisée de votre application. L'exécution de grunt
seule exécute une tâche default
que le générateur a configurée pour l'analyse lint, les tests et la compilation:
grunt.registerTask('default', [
'jshint',
'test',
'build'
]);
La tâche jshint
ci-dessus vérifie votre fichier .jshintrc
pour connaître vos préférences, puis l'exécute sur tous les fichiers JavaScript de votre projet. Pour obtenir la liste complète des options disponibles avec JSHint, consultez la documentation.
La tâche test
ressemble à ceci. Elle peut créer et diffuser votre application pour le framework de test que nous recommandons, Mocha. Il exécute également vos tests à votre place:
grunt.registerTask('test', [
'clean:server',
'createDefaultTemplate',
'jst',
'compass',
'connect:test',
'mocha'
]);
Étant donné que notre application est assez simple, nous vous laisserons écrire les tests dans un exercice distinct. Notre processus de compilation doit gérer d'autres éléments. Voyons ce que la tâche grunt build
définie dans notre Gruntfile.js
va faire:
grunt.registerTask('build', [
'clean:dist', // Clears out your .tmp/ and dist/ folders
'compass:dist', // Compiles your Sassiness
'useminPrepare', // Looks for <!-- special blocks --> in your HTML
'imagemin', // Optimizes your images!
'htmlmin', // Minifies your HTML files
'concat', // Task used to concatenate your JS and CSS
'cssmin', // Minifies your CSS files
'uglify', // Task used to minify your JS
'copy', // Copies files from .tmp/ and app/ into dist/
'usemin' // Updates the references in your HTML with the new files
]);
Exécutez grunt build
. Une version prête à être mise en production de votre application devrait être créée et prête à être distribuée. Essayons-la.
Opération réussie.
Si vous rencontrez des difficultés, vous pouvez consulter une version précompilée de polymer-blog sur https://github.com/addyosmani/polymer-blog.
Que nous réserve le futur ?
Les composants Web sont encore en cours d'évolution, et les outils qui les entourent le sont également.
Nous étudions actuellement comment concaténer les importations HTML pour améliorer les performances de chargement via des projets tels que Vulcanize (un outil du projet Polymer) et comment l'écosystème des composants pourrait fonctionner avec un gestionnaire de paquets tel que Bower.
Nous vous tiendrons informé dès que nous aurons des réponses plus précises à ces questions. En attendant, de nombreuses nouveautés vous attendent.
Installer Polymer de manière autonome avec Bower
Si vous préférez commencer à utiliser Polymer de manière plus légère, vous pouvez l'installer de manière autonome directement depuis Bower en exécutant la commande suivante:
bower install polymer
qui l'ajoutera à votre répertoire bower_components. Vous pouvez ensuite y faire référence manuellement dans votre index d'applications et vous lancer dans l'avenir.
Qu'en pensez-vous ?
Vous savez maintenant comment créer une application Polymer à l'aide de Web Components avec Yeoman. Si vous avez des commentaires sur le générateur, n'hésitez pas à nous les faire part dans les commentaires, à signaler un bug ou à publier un post sur le suivi des problèmes de Yeoman. Nous aimerions savoir si vous souhaitez que le générateur améliore d'autres aspects, car c'est grâce à votre utilisation et à vos commentaires que nous pouvons nous améliorer.