corejs

WebApps para toda la familia





@antaipt

¿Quiénes somos?

                 
Hristo Georigiev
Emilio Mena             

               
Álvaro Brito
Anthanh Pham

¿en qué trabajamos?





coreJS  => Bookland

Bookland


  • Plataforma de distribución de libros electrónicos

  • Modular
  • Mantenible
  • Fácilmente ampliable
  • Tecnologías reutilizables
  • Módulos reutilizables
  • Configurable

core JS



  • Core tecnológico robusto y consolidado
  • Válido para desarrollar cualquier WebApp
  • Adaptable
  • Reutilizable
  • Escalable
  • Mantenible
  • Workflow de desarrollo definido


stack

tecnológico






       +


stack tecnológico


Core

  • Backbone
  • Marionette
  • JQuery
  • Underscore
  • Handlebars
  • RequireJS

    stack tecnológico



    i18n

    • i18next
    • moment.js
    • numeral.js

    stack tecnológico



    Testing

    • mocha.js
    • chai.js
    • SinonJS
    • PhantomJS

    stack tecnológico



    Tooling

    • Grunt
    • Bower
    • Node
    • npm
    • compass
    • Sublime


    Arquitecturas

    webapp

    aplicaciones ambiciosas

    Backbone

    aplicaciones ambiciosas

    Marionette

    Backbone <=> Marionette


    Aplicación básica



    aplicación monolítica


    aplicación escalable

    core-base
    core-modules



    core Js

    Desde dentro

    estructura del proyecto

    .
    ├── init-env.sh             // Script de inicialización del proyecto
    ├── pom.xml                 // Maven stuff
    ├── package.json            // Dependencias de desarrollo (npm)
    ├── bower.json              // Dependencias con librerías externas
    ├── README.md               // Este documento
    ├── target                  // Workspace de temporales de Grunt
    ├── src/test                // Workspace de test
    └── src/main/webapp         // Workspace de desarollo de Grunt
        ├── stylesheets         // Hojas de estilo SASS
        └── scripts
            ├── app.js          // Contexto de aplicación        ├── main.js         // Script que arranca la aplicación
            ── engine          // Componentes internos de la aplicación
                ├── services.js // Comunicación con Backend
                ├── common.js   // Parámetros de la app
                ├── factory.js  // Factoría de objetos
                ├── locale.js   // Módulo de i18n
                ├── logger.js   // Módulo de log
                ├── polyfills.js// Polyfill varios
                ├── utils.js    // Funciones varias
                ├── user.js     // Autenticación y gestión de usuario
                ├── resource.js // Librería para realizar peticiones a backend            ├── session.js  // Gestión d elos datos de sesión del usuario
                ├── router.js   // Enrutador de la webapp
                ├── ...
                └── start.js    // Inicializador de módulo

    componentes principales

    Marionette.Application (I)

    • Contexto de aplicación
    'use strict';
    /* global define */
    define([
        'app',
    ], function(app) {
    	// Code here!
    });

    componentes principales

    Marionette.Application (II)

    • Inicialización distribuida

    app.addInitializer(function() {
        // Initialization code here
    });

    componentes principales

    Marionette.Application (III)

    • Regiones principales
    app.addRegions({
        header: 'header',
        main: 'main',
        footer: 'footer'
    });
        
    app.header.show(app.factory.new('HeaderView'));
    

    componentes principales

    Factorías

    • Componente específico del proyecto
    • Encapsular la creación de objectos
    • Mejora la testeabilidad de los módulos

    var HeaderView = Backbone.Marionette.ItemView.extend({...});
    app.factory.add('HeaderView', HeaderView);
    app.header.show(app.factory.new('HeaderView'));
    

    componentes principales

    Marionette.ItemView

    • Hereda de Backbone.View
    • Reducción de código
    • Gestión de recursos optimizada

    Marionette.CollectionView

    • Similar a ItemView
    • Renderiza varias veces el mismo componente

    componentes principales

    Marionette.Region

    • Gestión de componentes
    • Igual que en Marionette.Application

    componentes principales

    RequireJS

    • Definición de dependencias del proyecto
    • Orden de concatenación en build-time



    DEMO


    Desarollo

    de Módulos

    Manos a la obra

    estructura de un módulo


    src/main/webapp
    ├── res
    │   └──config
    │       ├──config.json      // Configuración de la webapp
    │       └──myModule.json    // Configuración del módulo 'myModule'
    └── scripts
        ├──define.js            // definición de dependencias requirejs
        ├──main.js              // Script principal de la webapp
        └──modules              // Directorios de módulos de la webapp
            ├──loader.js        // Declaración de módulos a cargar
            └──myModule         // Nombre del módulo
                ├── start.js    // Inicialización y dependencias            ├── css             // Hojas de estilo
                ├── collections // Colecciones del módulo
                ├── layouts     // Layouts del módulo
                ├── models      // Modelos del módulo
                ├── templates   // Templates "Handlebars"
                └── views       // Vistas (ItemView/CollectionView)

    desarrollar un template


    Teniendo un modelo Backbone:
    var MyModel = Backbone.Model.extend({});
    myModel = new MyModel({
        foo: 'Hi',
        bar: 'Álvaro'
    });

    Un template válido Handlebars:
    <div>
        <h1>{{foo}}</h2>
        <p>{{bar}}</p>
    </div>

    Desarrollar vistas

    Marionette.ItemView
    'use strict';
    /* global define */
    define(['app', 'jquery', 'underscore', 'backbone', 'backbone.marionette'], function(app, $, _, Backbone) {
        var MyView = Backbone.Marionette.ItemView.extend({        template: function(serializedModel) {
                // Load the compiled template generated by
                // 'modules/myModule/templates/myTemplate.html'
                return app.jst['myModule/myTemplate'](serializedModel);
            }
        });
    
        return MyView;
    });

    desarrollar vistas

    Marionette.CollectionView

    'use strict';
    /* global define */
    define(['app', 'jquery', 'underscore', 'backbone', 'backbone.marionette'], function(app, $, _, Backbone) {
        var MyCollectionView = Backbone.Marionette.CollectionView.extend({
            // Reference to the ItemView specification
            itemView: function() {           return app.views.get('MyView')        }
        });
    
        return MyCollectionView;
    });

    renderizar vistas



    En una Region
    app.regionName.show(app.views.create('MyView'));


    De forma directa
    var myView = app.views.create('MyView');$('body').html(myView.render().el);

    extender el router



    var myHandler = function() {
        var myModel = app.models.create('MyModel');
        app.myRegion.show(app.views.create('MyView', {
            model: myModel
        }));
    };
    
    app.addInitializer(function() {    // Define router paths    app.router.route('myroute', 'trigger:this:event', myHandler);
    });

    juntarlo todo

    start.js

    • Punto de inicio del módulo
    • Define las dependencias del módulo
      • Modelos/Collectiones
      • Vistas
      • Templates
      • Otras librerías
    • Define los manejadores del router
    • Añade fase de inicialización
      • Actualiza las factorías
      • Añade nuevas rutas

    start.js (ejemplo)

    var myHandler = function() {
        var myModel = app.models.create('MyModel');
        app.myRegion.show(app.views.create('MyView', {
            model: myModel
        }));
    };
    app.addInitializer(function() { // Add models to factory app.models.add('MyModel', MyModel); // Add views to factory app.views.add('MyView', MyView); // Define router paths app.router.route('myroute', 'trigger:this:event', myHandler); });
    app.on('initialize:after', function() { // Code after initialization here app.myRegion.show(app.views.create('MyCollectionView')); });

    integrar módulo

    main.js

    Definición de los módulos a incluir
    'use strict';
    /* globals require, console */
    require([
        'app',
        'jquery',
        'underscore',
        'backbone',
    
        // Modules
        'modules/engine/start',
        'modules/myModule/start' // <== Module declaration
    ], function(app, $, _, Backbone) { ... });

    comunicación entre módulos


    • Módulos que exponen eventos
    • Módulos que responden a eventos

    Comunicación entre módulos




    • Comunicación entre componentes
      • EventAggregator
      • RequestResponse
      • Commands

    comunicación entre módulos

    Marionette.EventAggregator

    • Un evento => N suscriptores

    app.vent.on("foo", function(args){
        console.log("foo event" + args.bar);
    });

    app.vent.trigger("foo", {bar: true});

    comunicación entre módulos

    Marionette.RequestResponse

    • Un evento => una respuesta

    app.reqres.setHandler("foo", function(){
        return "foo requested. this is the response";
    });
    

    var result = app.reqres.request("foo");
    console.log(result);

    comunicación entre módulos

    Marionette.Commands

    • Un evento => una acción

    app.commands.setHandler("foo", function(bar){
      console.log(bar);
    });

    app.execute("foo", "baz");

    silkroad js client (draft)

    Propuesta de interfaz con SilkRoad

    app.api.auth(params);
    var resource = app.api.setResource('books/id/author');resource.page(3, 15);resource.gt('price', 50);resource.eq('year', 2013);resource.sort('name', 'asc');// ... more operators: lt, lte, gte, neq, ...resource.keywords(['Harry', 'Potter', 'Fénix']);
    var promise = resource.execute()promise.then(function(){ })    .done(function(){ })    .fail(function(){ });

    tests unitarios


    • mocha
    • chai
    • SinonJS


    DEMO


    "Escribe los tests como si quisieras contar una historia"

    workflow

    Automatizando con Grunt


    Desarrollo
    grunt server
    jst => compass => connect:dev => livereload => open => watch

    Tests   
    grunt test
    jst => compass => connect:test

    workflow

    Automatizando con Grunt


    Producción
    grunt 
    jshint => [test] => jst => compass => concat => imgmin => htmlmin => cssmin => jsmin => rev

    documentación






    ¿preguntas?



    anthanh.pham@bq.com

    coreJS

    By Anthanh

    coreJS

    Propuesta de core tecnológico para el desarollo de webApps

    • 2,101