Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Peut-on encore coder des "webapps" modernes sans une batterie d'outils à la c...?

Peut-on encore coder des "webapps" modernes sans une batterie d'outils à la c...?

Présentation préparée spécialement pour la conférence RivieraDev 2015

http://www.rivieradev.fr/

Au départ, j'avais choisi le JavaScript parce que c'était simple à mettre en oeuvre, que le langage est plutôt facile d'accès (si si!). Et puis JavaScript a gagné en popularité (probablement à cause de la disparition de Flash) et certains se sont dit qu'il fallait rattrapé Java en termes d'outillage. Du coup, maintenant, la moindre webapp nécessite d'avoir installé npm, bower, grunt, yeoman etc... et de télécharger la terre entière. Si en plus tu ne connais pas Angular, tu pars avec un handicap ... Et pourtant il est possible de faire des webapps modernes sans ces outils (presque à l'ancienne) avec des frameworks légers, sans grunt & co, sans transpiler votre code, avec des ""custom tags"" légers à la React (un peu comme des webcomponents sans Polymer), sans les directives compliquées et difficilement maintenables d'Angular. Ce sera l'occasion de voir la différence entre ""custom tags"" et ""web components"" (ou la différence entre le virtual dom et le shadow dom) Je vous démontrerais ça en vous présentant le framework Riot.js qui permet de faire des ""custom tags"" sans se fatiguer (enfin pas trop). Nous verrons aussi à quel point il est facile de l'utiliser avec d'autres frameworks ... Et si vous êtes sages, on fera même un peu d'EcmaScript6 ;)

le codes des démos sont par ici: https://github.com/k33g/play-with-riot

Philippe CHARRIERE

June 14, 2015
Tweet

More Decks by Philippe CHARRIERE

Other Decks in Programming

Transcript

  1. #riot #rivieradev Peut-on encore coder des "webapps" modernes sans une

    batterie d'outils à la c...? #riot #rivieradev
  2. #riot #rivieradev Architecture (JS) Web “Moderne” “Serveur d’API” Navigateur Base

    de données DOM + JS View Controller Model SGBDR, NoSQL REST APIs
  3. #riot #rivieradev Architecture (JS) Web “Moderne” “Serveur d’API” Navigateur Base

    de données DOM + JS View Controller Model SGBDR, NoSQL REST APIs SPA
  4. #riot #rivieradev Avant Navigateur DOM + JS Serveur App° View

    Controller Model Navigateur DOM + JS View Controller Model “Serveur d’API” REST APIs HTML JSON Après
  5. #riot #rivieradev var Human = Backbone.Model.extend({
 urlRoot: "/api/humans",
 idAttribute: "_id"

    // mongoDb compliant
 });
 
 var Humans = Backbone.Collection.extend({
 model: Human,
 url: "/api/humans"
 });
  6. #riot #rivieradev var bob = new Human({
 firstName: "Bob",
 lastName:

    "Morane"
 });
 
 var john = new Human({
 firstName: "John",
 lastName: "Doe"
 });
 
 bob.set({firstName:"Bobby"});
 console.log(bob.get("firstName"));
  7. #riot #rivieradev bob.save()
 .then(function(data) {/* saved */})
 .fail(function(error) {/* ouch

    */});
 
 john.save()
 .then(function(data) {/* saved */})
 .fail(function(error) {/* ouch */});
 
 var humansColl = new Humans();
 
 humansColl.fetch().then(function(humans) {
 console.log(humansColl);
 });
  8. #riot #rivieradev var Thing = function() {};
 Thing.extend = Backbone.Model.extend


    
 var Animal = Thing.extend({
 toString : function() { console.log("hello : ", this); },
 constructor : function Animal (name) {
 this.name = name
 }
 });
 
 //Dog inherits of Animal
 var Dog = Animal.extend({
 constructor : function Dog (name){
 //call parent constructor
 Dog.__super__.constructor.call(this, name);
 }
 });
  9. #riot #rivieradev var HumansView = Backbone.View.extend({
 el:"humans",
 initialize: function() {


    this.template = _.template($("#humans_tpl").html())
 },
 render: function() {
 this.$el.html(this.template({humans:this.collection.models}))
 }
 })
 
 var humansCollection = new Humans();
 var humansView = new HumansView({collection:humansCollection})
 
 humansCollection.fetch().then(function() {
 humansView.render();
 }); <humans></humans>
 
 <script type="text/template" id="humans_tpl">
 <ul>
 <% _.each(humans ,function(human){ %>
 <li><%= human.get("firstName") %> <%= human.get("lastName") %></li>
 <% }); %>
 </ul>
 </script>
  10. #riot #rivieradev 
 var HumanItemView = Backbone.View.extend({
 tagName:"li",
 initialize: function()

    {
 this.template = _.template('<%= human.get("firstName") %> <%= human.get("lastName") %>')
 },
 render: function() {
 this.$el.html(this.template({human:this.model}))
 return this
 }
 })
 
 var HumansListView = Backbone.View.extend({
 tagName:"ul",
 el:"humans-list",
 initialize: function() {},
 render: function() { var item;
 this.$el.empty();
 this.collection.each(function(model) {
 item = new HumanItemView({model:model});
 this.$el.append(item.render().el)
 }, this)
 }
 })
 var humansCollection = new Humans();
 
 var humansListView = new HumansListView({collection:humansCollection})
 
 humansCollection.fetch().then(function(data) {
 humansListView.render()
 })
  11. #riot #rivieradev this.App = {};
 
 (function(app) {
 
 app.models

    = {};
 app.collections = {};
 
 return app;
 })(this.App); (function (app) {
 
 app.models.Human = Backbone.Model.extend({
 urlRoot:"/api/humans",
 idAttribute: "_id"
 });
 
 app.collections.Humans = Backbone.Collection.extend({
 model: app.models.Human,
 url: "/api/humans"
 });
 
 return app;
 
 }(App));
 var bob = new app.models.Human({
 firstName: "Bob",
 lastName: "Morane"
 });
 
 var john = new app.models.Human({
 firstName: "John",
 lastName: "Doe"
 });
 
 var humansColl = new app.collections.Humans();
  12. #riot #rivieradev <body ng-app="app">
 <h2>Angular</h2>
 
 <humans></humans>
 
 <script>
 var

    app = angular.module("app", ['human.directive', 'humans.directive']);
 var humansCollection = new Humans();
 app.value("humansCollection", humansCollection);
 </script>
 
 </body>
  13. #riot #rivieradev var humansTag = angular.module('humans.directive', []);
 
 humansTag.directive('humans',['humansCollection', function(humansCollection)

    {
 return {
 template: '<ul ng-repeat="human in humans"><human model="human"></human></ul>',
 scope : {},
 link: function (scope, element, attributes) {
 scope.humans = humansCollection.models
 
 humansCollection.fetch().then(function() {});
 
 humansCollection.on("sync", function() {
 scope.$apply()
 });
 }
 };
 }]);

  14. #riot #rivieradev var humanTag = angular.module('human.directive', []);
 
 humanTag.directive('human',function() {


    return {
 template: '<li>{{human.get("firstName")}} {{human.get("lastName")}}</li>',
 scope : {
 human: '=model'
 },
 link: function (scope, element, attributes) {
 scope.human.on("change", function() {
 scope.$apply()
 })
 }
 };
 });
  15. #riot #rivieradev Virtual DOM abstraction(s) du DOM 2 copies du

    DOM (l’original + la v° mise à jour) appliquer seulement les différences
  16. #riot #rivieradev var HumansList = React.createClass({
 
 componentWillMount: function() {


    var humansCollection = new Humans();
 humansCollection.fetch().then(function() {
 this.setState({humans: humansCollection.models})
 }.bind(this))
 },
 getInitialState: function() {
 return {humans:[]};
 },
 render: function() {
 var human = this.state.humans.map(function(model) {
 return(
 <li>
 {model.get("firstName")} {" "} {model.get("lastName")}
 </li>
 );
 });
 return (
 <ul>
 {human}
 </ul>
 );
 }
 });
 
 React.render(
 <HumansList />,
 document.querySelector('humans-list');
 );
  17. #riot #rivieradev Shadow DOM = DOM encapsulé conceptuellement la même

    chose que le Virtual DOM 1 élément (shadow host) a un shadow root (root du shadow tree) le rendu est fait à partir du shadow root
  18. #riot #rivieradev <link rel="import" href="../js/vendors/polymer/polymer.html">
 
 <dom-module id="humans-list">
 <template>
 <ul>


    <template is="dom-repeat" items="{{humans}}">
 <li> <human-record model={{item}}></human-record> </li>
 </template>
 </ul>
 
 </template>
 </dom-module>
 
 <script>
 Polymer({
 is: "humans-list",
 setHumans: function(models) {
 this.humans = models
 },
 ready: function() {
 this.humansCollection = new Humans(); this.humansCollection.fetch().then(function(humans) {
 this.setHumans(this.humansCollection.models)
 }.bind(this));
 
 this.humansCollection.on("all", function() { this.setHumans(this.humansCollection.models)
 }.bind(this));
 }
 });
 </script> 
 <dom-module id="human-record">
 <template>
 <span>{{human.firstName}}</span> <span>{{human.lastName}}</span>
 </template>
 </dom-module>
 
 
 <script>
 Polymer({
 is: "human-record",
 properties: {
 model: Object
 },
 ready: function() {
 this.human = this.model.toJSON()
 
 this.model.on("change", function() {
 this.human = this.model.toJSON()
 }.bind(this))
 }
 });
 
 </script>
  19. #riot #rivieradev très sympa à apprendre mais beaucoup de choses

    à assimiler Polyfill… pas léger avec BB … bof (à creuser)