martes, 22 de diciembre de 2015

El Demo del Día: Aplicación de Simple Página (SPA) en ASP.NET MVC

Aplicación de Simple Página (SPA) en ASP.NET MVC

Después de mucho tiempo vamos a presentar un nuevo Demo, esta vez comparando una Aplicación de Múltiples Páginas (MPA) con una Aplicación de Simple Página (SPA), pero sin usar ningún Framework SPA como AngularJS, Knockout, Ember, Meteor, Kendo UI, etc.

Introducción a una SPA

El modelo por defecto en ASP.NET sea WebForms o MVC es MPA, quiere decir que nuestro sitio web se compone de varias páginas las cuales se solicitan desde el cliente una a una y cada una descarga sus archivos necesarios: HTML, JavaScript, CSS, Imágenes, Fuentes, etc.
En cambio si nuestro sitio solo tuviera una simple página solo se cargaría una sola vez todos los archivos.

Ventajas de una SPA

La gran ventaja de una Aplicación de Simple Página (SPA) es que evita conectarse varias veces al servidor para solicitar cada página, es decir, favorece el trabajo desconectado, ya que al haber una sola página se pueda cargar todos los datos necesarios al inicio, así como los JavaScripts y las hojas de estilo.

Trabajar con una sola página ayuda a la Performance, ya que evita conexiones innecesarias al servidor web.

Usos de una SPA

Generalmente, los sitios web móviles usan este modelo, ya que solo se carga una página y se va presentando secciones (llamadas cartas o barajas) de ésta, muchos de los Frameworks para Aplicaciones Web Móviles trabajan de esta forma, por ejemplo jQuery Mobile, Bootstrap, etc.

Pero si nuestra Aplicación Web no tiene demasiadas páginas ni datos que cargar, también podemos usar este modelo, ahorrando conexiones al servidor, es decir, trabajando en forma desconectada.

Características de una SPA

Existen muchas características de una SPA:
- La principal es que la aplicación solo tenga una página.
- Aunque no es exclusividad de una SPA, actualmente el Diseño Web debe ser Adaptativo (Responsive Web Design).
- Otra característica importante (que también no es exclusividad de SPA) es que debe hacer llamadas Asíncronas JavaScript HTTP: AJAX (Xml), AJAJ (JSON) o AJAS (Strings).

Ejemplo de Comparación entre MPA y SPA en ASP.NET MVC

A continuación vamos a presentar un ejemplo donde comparamos una Aplicación sobre Pedidos que tiene los 2 modelos:

- MPA: Compuesto por un Controlador llamado MPA que tiene 4 métodos de acción y 4 vistas, llamadas Login, Categoria, Producto y Pedido. La navegación entre cada una implica ir al servidor y esperar su respuesta, para lo cual a propósito se ha puesto un tiempo de espera. Este modelo usa 4 archivos de JavaScript, uno para cada página.

- SPA: Compuesto por un Controlador llamado SPA que tiene solo un método de acción y una vista llamada Pedido. Por otra parte solo hay un archivo de JavaScript llamado Todo.js que realiza la navegación entre páginas (divs) y que no viaja al servidor sino solo se hace en el cliente.

Crear una Aplicación ASP.NET MVC 4 en C#

- Abrir Visual Studio 2012 y crear un proyecto de tipo "Aplicación web de ASP.NET MVC4" y asignarle como nombre: "SinglePageApplication".

- Seleccionar la opción "Vacio" y como motor de vista "Razor" y "Aceptar".

Crear el Controlador MPA

- Clic derecho a la carpeta Controllers y seleccionar "Agregar" y luego "Controlador".

- Ingresar como nombre "MPAController" y luego escribir el siguiente código:

using System;
using System.Web;
using System.Web.Mvc;

namespace SinglePageApplication.Controllers
{
    public class MPAController : Controller
    {
        public ActionResult Login()
        {
            return View();
        }

        public ActionResult Categoria()
        {
            //Simular que esta conectandose a la BD para traer las Categorias
            System.Threading.Thread.Sleep(2000);
            return View();
        }

        public ActionResult Producto()
        {
            //Simular que esta conectandose a la BD para traer los Productos x Categoria
            System.Threading.Thread.Sleep(4000);
            return View();
        }

        public ActionResult Pedido()
        {
            //Simular que esta leyendo del TempData los Pedidos
            System.Threading.Thread.Sleep(1000);
            return View();
        }
    }
}

Crear una Hoja de Estilo para todas las vistas

- Crear una carpeta para los archivos CSS llamado: "Estilos".

- Crear una hoja de estilo llamada "ACME.css" dentro de la carpeta Estilos y escribir el siguiente código:

body {
    background-color:aqua;
    width:100%;
}
.Titulo {
    background-color:blue;
    color:white;
    font-family:Arial;
    font-size:xx-large;
    text-align:center;  
}
.Subtitulo {
    background-color:white;
    color:blue;
    font-family:Arial;
    font-size:x-large;
    text-align:center;
}
table {
    width:100%;
}
.FilaCabecera {
    background-color:lightgray;
    color:black;
}
.FilaDatos {
    background-color:white;
    color:black;
}
.Pagina {
    display:none;
}

Crear las Vistas para MPA

- Ir al controlador MPA, clic derecho sobre el nombre del método "Login" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Login</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divLogin">
        <div id="divCabeceraLogin">
            <div id="divTituloLogin" class="Titulo">
                <span id="spnTitulo">Aplicación de Múltiples Paginas (MPA)</span>
            </div>
            <div id="divSubtituloLogin" class="Subtitulo">
                <span id="spnSubtituloLogin">Login del Sistema</span>
            </div>
        </div>
        <div id="divCuerpoLogin">
            <div id="divEtiquetaUsuario">
                <span id="spnUsuario">Usuario: </span>
            </div>
            <div id="divTextoUsuario">
                <input id="txtUsuario" type="text" />
            </div>
            <div id="divEtiquetaClave">
                <span id="spnClave">Clave: </span>
            </div>
            <div id="divTextoClave">
                <input id="txtClave" type="password" />
            </div>
            <div id="divBotonesLogin">
                <input id="btnAceptar" type="button" value="Aceptar" />
            </div>
        </div>
        <div id="divPieLogin">
            <div id="divUbicacion" class="Subtitulo">
                <span id="spnUbicacion">Lima - Perú</span>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Login.js"></script>
</body>
</html>

- Ir al controlador MPA, clic derecho sobre el nombre del método "Categoria" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Categoria</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divCategoria">
        <div id="divCabeceraCategoria">
            <div id="divSubtituloCategoria" class="Subtitulo">
                <span id="spnSubtituloCategoria">Selecciona una Categoria</span>
            </div>
        </div>
        <div id="divListaCategoria">
            <span id="spnListaCategoria">Aqui se debe mostrar un lista de Categorias</span>
        </div>
        <div id="divPieCategoria">
            <div id="divNavegarCategoria" class="Subtitulo">
                <a id="aCatProd" href="~/MPA/Producto">Productos</a>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Categoria.js"></script>
</body>
</html>

- Ir al controlador MPA, clic derecho sobre el nombre del método "Producto" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Producto</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divProducto">
        <div id="divCabeceraProducto">
            <div id="divSubtituloProducto" class="Subtitulo">
                <span id="spnSubtituloProducto">Agrega Productos a tu Pedido</span>
            </div>
        </div>
        <div id="divListaProducto">
            <span id="spnListaProducto">Aqui se debe mostrar un lista de Productos</span>
        </div>
        <div id="divPieProducto">
            <div id="divNavegarProducto" class="Subtitulo">
                <a id="aProdPed" href="~/MPA/Pedido">Pedidos</a>
                <a id="aProdCat" href="~/MPA/Categoria">Regresar</a>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Producto.js"></script>
</body>
</html>

- Ir al controlador MPA, clic derecho sobre el nombre del método "Pedido" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Pedido</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divPedido">
        <div id="divCabeceraPedido">
            <div id="divSubtituloPedido" class="Subtitulo">
                <span id="spnSubtituloPedido">Agrega Productos a tu Pedido</span>
            </div>
        </div>
        <div id="divListaPedido">
            <span id="spnListaPedido">Aqui se debe mostrar un lista de Pedidos</span>
        </div>
        <div id="divPiePedido">
            <div id="divNavegarPedido" class="Subtitulo">
                <a id="aPedCat" href="~/MPA/Categoria">Regresar</a>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Pedido.js"></script>
</body>
</html>

Crear los JavaSripts para MPA

- Crear una carpeta para los archivos js llamado: "Scripts"

- Crear una archivo de JavaScript llamado "Login.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    var btnAceptar = document.getElementById("btnAceptar");
    btnAceptar.onclick = function () {
        var txtUsuario = document.getElementById("txtUsuario");      
        if (txtUsuario.value == "") {
            alert("Ingresa el Usuario");
            txtUsuario.focus();
            return false;
        }
        var txtClave = document.getElementById("txtClave");
        if (txtClave.value == "") {
            alert("Ingresa la Clave");
            txtClave.focus();
            return false;
        }
        if (txtUsuario.value == "Luis" && txtClave.value == "123") {
            window.location.href = "MPA/Categoria";
        }
        else {
            alert("Login invalido");
        }
    }
}

- Crear una archivo de JavaScript llamado "Categoria.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    alert("Cargando Categorias");
}

- Crear una archivo de JavaScript llamado "Producto.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    alert("Cargando Productos");
}

- Crear una archivo de JavaScript llamado "Pedido.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    alert("Cargando Pedidos");
}

Configurar el Inicio del MPA

- Ir a la carpeta "App_Start" y abrir el archivo "RouteConfig.css" y cambiar el nombre del controlador y la acción que inicia.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace SinglePageApplication
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "MPA", action = "Login", id = UrlParameter.Optional }
            );
        }
    }
}

Probar y Ejecutar la Aplicación de Múltiples Páginas (MPA)

- Grabar y ejecutar la aplicación pulsando F5 y se mostrará una ventana similar a la siguiente figura:


- Ingresar como usuario "Luis" y como clave "123" y "Aceptar", observando que se demora en cargar la segunda página de Categoria, similar a la siguiente figura:


- Clic al enlace de Productos y después de esperar un momento se mostrará la página de Producto, similar a la siguiente figura:


- Clic al enlace de Pedidos y después de esperar un momento se mostrará la página de Pedido, similar a la siguiente figura:


- Si deseas en cualquier página puedes seleccionar el enlace "Regresar".

Nota: En todos los enlaces al dar clic se irá al servidor para cargar la página ya que el modelo es MPA.

Crear el Controlador SPA

- Clic derecho a la carpeta Controllers y seleccionar "Agregar" y luego "Controlador".

- Ingresar como nombre "SPAController" y luego escribir el siguiente código:

using System;
using System.Web;
using System.Web.Mvc;

namespace SinglePageApplication.Controllers
{
    public class SPAController : Controller
    {
        public ActionResult Pedido()
        {
            return View();
        }
    }
}

Crear la Vista para SPA

- Ir al controlador SPA, clic derecho sobre el nombre del método "Pedido" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Pedido</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divTodo">
        <div id="divLogin" class="Pagina">
            <div id="divCabeceraLogin">
                <div id="divTituloLogin" class="Titulo">
                    <span id="spnTitulo">Aplicación de Simple Pagina (SPA)</span>
                </div>
                <div id="divSubtituloLogin" class="Subtitulo">
                    <span id="spnSubtituloLogin">Login del Sistema</span>
                </div>
            </div>
            <div id="divCuerpoLogin">
                <div id="divEtiquetaUsuario">
                    <span id="spnUsuario">Usuario: </span>
                </div>
                <div id="divTextoUsuario">
                    <input id="txtUsuario" type="text" />
                </div>
                <div id="divEtiquetaClave">
                    <span id="spnClave">Clave: </span>
                </div>
                <div id="divTextoClave">
                    <input id="txtClave" type="password" />
                </div>
                <div id="divBotonesLogin">
                    <input id="btnAceptar" type="button" value="Aceptar" />
                </div>
            </div>
            <div id="divPieLogin">
                <div id="divUbicacion" class="Subtitulo">
                    <span id="spnUbicacion">Lima - Perú</span>
                </div>
            </div>
        </div>
        <div id="divCategoria" class="Pagina">
            <div id="divCabeceraCategoria">
                <div id="divSubtituloCategoria" class="Subtitulo">
                    <span id="spnSubtituloCategoria">Selecciona una Categoria</span>
                </div>
            </div>
            <div id="divListaCategoria">
                <span id="spnListaCategoria">Aqui se debe mostrar un lista de Categorias</span>
            </div>
            <div id="divPieCategoria">
                <div id="divNavegarCategoria" class="Subtitulo">
                    <a id="aCatProd" href="#" data-url="divProducto">Productos</a>
                </div>
            </div>
        </div>
        <div id="divProducto" class="Pagina">
            <div id="divCabeceraProducto">
                <div id="divSubtituloProducto" class="Subtitulo">
                    <span id="spnSubtituloProducto">Agrega Productos a tu Pedido</span>
                </div>
            </div>
            <div id="divListaProducto">
                <span id="spnListaProducto">Aqui se debe mostrar un lista de Productos</span>
            </div>
            <div id="divPieProducto">
                <div id="divNavegarProducto" class="Subtitulo">
                    <a id="aProdPed" href="#" data-url="divPedido">Pedidos</a>
                    <a id="aProdCat" href="#" data-url="divCategoria">Regresar</a>
                </div>
            </div>
        </div>
        <div id="divPedido" class="Pagina">
            <div id="divCabeceraPedido">
                <div id="divSubtituloPedido" class="Subtitulo">
                    <span id="spnSubtituloPedido">Agrega Productos a tu Pedido</span>
                </div>
            </div>
            <div id="divListaPedido">
                <span id="spnListaPedido">Aqui se debe mostrar un lista de Pedidos</span>
            </div>
            <div id="divPiePedido">
                <div id="divNavegarPedido" class="Subtitulo">
                    <a id="aPedCat" href="#" data-url="divCategoria">Regresar</a>
                </div>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Todo.js"></script>
</body>
</html>

Crear el JavaSript para SPA

- Crear una archivo de JavaScript llamado "Todo.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    //Mostrar la primera pagina
    var divLogin = document.getElementById("divLogin");
    if (divLogin) {
        divLogin.style.display = "inline";
        scriptLogin();
    }
    //Programar toda la navegación
    var enlaces = document.getElementsByTagName("a");
    if (enlaces != null && enlaces.length > 0) {
        var n = enlaces.length;
        var enlace;
        var pagina;
        var script;
        for (var i = 0; i < n; i++) {
            enlace = enlaces[i];
            enlace.onclick = function () {
                ocultarPaginas();
                var id = this.getAttribute("data-url");
                pagina = document.getElementById(id);
                if (pagina != null) {
                    pagina.style.display = "inline";
                    script = id.replace("div", "script");
                    window[script]();
                }
            }
        }
    }
}

function ocultarPaginas() {
    var paginas = document.getElementsByClassName("Pagina");
    if (paginas != null && paginas.length > 0) {
        var n = paginas.length;
        var pagina;
        for (var i = 0; i < n; i++) {
            pagina = paginas[i];
            pagina.style.display = "none";
        }
    }
}

function scriptLogin() {
    var btnAceptar = document.getElementById("btnAceptar");
    btnAceptar.onclick = function () {
        var txtUsuario = document.getElementById("txtUsuario");
        if (txtUsuario.value == "") {
            alert("Ingresa el Usuario");
            txtUsuario.focus();
            return false;
        }
        var txtClave = document.getElementById("txtClave");
        if (txtClave.value == "") {
            alert("Ingresa la Clave");
            txtClave.focus();
            return false;
        }
        if (txtUsuario.value == "Luis" && txtClave.value == "123") {
            var divCategoria = document.getElementById("divCategoria");
            if (divCategoria) {
                ocultarPaginas();
                divCategoria.style.display = "inline";
                scriptCategoria();
            }
        }
        else {
            alert("Login invalido");
        }
    }
}

function scriptCategoria() {
    alert("Cargando Categorias");
}

function scriptProducto() {
    alert("Cargando Productos");
}

function scriptPedido() {
    alert("Cargando Pedidos");
}

Nota: En el evento load de la ventana se muestra solo el primer div (Login) y el resto esta oculto por el estilo de la clase Pagina. Además se obtiene todos los enlaces y se programa para que se navegue al div que especifique el atributo "data-url" ejecutando su script asociado que debe tener el prefijo script seguido del nombre usando: window[script]().

Configurar el Inicio del SPA

- Ir a la carpeta "App_Start" y abrir el archivo "RouteConfig.css" y cambiar el nombre del controlador y la acción que inicia.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace SinglePageApplication
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "SPA", action = "Pedido", id = UrlParameter.Optional }
            );
        }
    }
}

Probar y Ejecutar la Aplicación de Simple Página (SPA)

- Grabar y ejecutar la aplicación pulsando F5 y se mostrará una ventana similar a la siguiente figura:


- Ingresar como usuario "Luis" y como clave "123" y "Aceptar", observando que no se demora en cargar nada la segunda página de Categoria ya que es un div, similar a la siguiente figura:


- Clic al enlace de Productos e inmediatamente se mostrará la página de Producto ya que es un div, similar a la siguiente figura:


- Clic al enlace de Pedidos y e inmediatamente se mostrará la página de Pedido que también es un div, similar a la siguiente figura:


- Si deseas en cualquier página puedes seleccionar el enlace "Regresar"y navegará a la sección especificada.

Nota: En todos los enlaces al dar clic se ocultarán todos los divs y se mostrará uno solo ya que el modelo es SPA, es decir, no se va al servidor sino solo se muestra en el cliente.

Comentario Final

En este post un poco largo hemos querido mostrar como se puede crear sin ningún Framework de JavaScript una Aplicación de Simple Pagina (SPA) tan solo usando divs y un poco de JavaScript, lo cual es muy útil para trabajar en forma desconectada en aplicaciones pequeñas, por ejemplo, las aplicaciones web móviles.

Las personas que desean crear una SPA en MVC usando Frameworks, encontrarán muchos Blogs y Sitios Web, ya que para esto existe mucha información, tanto oficial como no oficial, por ejemplo les alcanzo un enlace del MSDN:
ASP.NET MVC 5: A .NET Developer Primer for SPA

Finalmente, como siempre hemos querido demostrar como hacerlo nosotros mismos sin necesidad de descargar nada, ni en el servidor ni en el cliente, ya que esto aumenta el tamaño de la aplicación perjudicando el ancho de banda, es decir, la performance.

Descarga del Código
SinglePageApplication

jueves, 17 de diciembre de 2015

El Libro del Día: Beginning Oracle Database 12c Administration

El Libro del Día: 2015-12-17

Titulo: Beginning Oracle Database 12c Administration
Autor: Ignatius Fernandez
Editorial: Apress
Nro Paginas: 370

Capítulos:
Part I: Database Concepts
Chapter 1: Relational Database Management Systems
Chapter 2: SQL and PL/SQL by Example
Chapter 3: Oracle Architecture
Part II: Database Implementation
Chapter 4: Planning
Part III: Database Support
Chapter 9: Taking Control
Chapter 10: Monitoring
Chapter 11: Fixing Problems
Chapter 12: Backups
Chapter 13: Recovery
Chapter 14: Database Maintenance
Chapter 15: The Big Picture and the Ten Deliverables
Part IV: Database Tuning
Chapter 16: Database Tuning
Chapter 17: SQL Tuning

Descarga:
Beginning_Oracle_Database_12c_Administration

martes, 15 de diciembre de 2015

El Libro del Día: Introducing SQL Server

El Libro del Día: 2015-12-15

Titulo: Introducing SQL Server
Autor: Mike McQuillan
Editorial: Apress
Nro Paginas: 397

Capítulos:
Chapter 1: What Is SQL Server
Chapter 2: Obtaining and Installing SQL Server
Chapter 3: Database Basics
Chapter 4: Tables
Chapter 5: Putting Good Tables Together
Chapter 6: Automating Deployment with SQLCMD
Chapter 7: NULLs and Table Constraints
Chapter 8: DML (or Inserts, Updates, and Deletes)
Chapter 9: Bulk Inserting Data
Chapter 10: Creating Data Import Scripts
Chapter 11: The SELECT Statement
Chapter 12: Joining Tables
Chapter 13: Views
Chapter 14: Indexes
Chapter 15: Transactions
Chapter 16: Functions
Chapter 17: Table-Valued Functions
Chapter 18: Stored Procedures Part 1
Chapter 19: Stored Procedures Part 2
Chapter 20: Bits and Pieces
Appendix A: SQL Data Types
Appendix B: Glossary
Appendix C: Common SQL Server System Objects
Appendix D: Exercises

Descarga:
Introducing_SQL_Server

miércoles, 9 de diciembre de 2015

Artículo - Pruebas de Performance

Pruebas de Performance

En este artículo veremos un caso práctico de pruebas del software: las pruebas de performance, que son las más necesarias en los sistemas web, debido al creciente incremento de usuarios y sobre todo de dispositivos que se pueden conectar a una aplicación web.

1. Criterios para Medir la Performance

Primero debemos entender que la medición de la performance de un sitio web se realiza a nivel de cada página, es decir, para medir la performance de todo el sitio web debemos medir la performance de cada página y luego hacer un promedio.

Entre las principales métricas para medir la performance de una página tenemos:
  • Tiempo de carga (Load Time)
  • Tiempo del primer byte recibido (First Byte)
  • Índice de velocidad (Speed Index)
  • Elementos del Modelo de Objetos del Documento (DOM Elements)
Por otra parte, estas métricas deben aplicarse en 2 momentos
  • La primera vez (First View)
  • Las demás veces (Repeat View)
Solo para recordar, hay que mencionar que los principales factores que afectan a la performance son:
  • Cantidad de solicitudes hechas por la página (Request)
  • Cantidad de datos enviados al cliente (Bytes)
Para obtener un buen puntaje debemos hacer la menor cantidad de solicitudes en cada página, es decir, usando pocos archivos CSS, JavaScript, Imágenes y Fuentes.

Además cada archivo debe tener la menor cantidad de datos, es decir, solo lo que se va a usar; en el caso de CSS las clases, en el caso de JavaScript las funciones y en el caso de las imágenes y las fuentes tienen que estar optimizadas.

2. Herramientas para Pruebas de Performance

Existen muchas herramientas para medir la performance, entre las más usadas en el mundo tenemos:

2.1. YSlow

Esta herramienta fue la primera en medir la performance y la primera versión fue creada por Steve Souders en Yahoo en el 2007, actualmente está disponible la versión 2.0 mantenida por Marcel Duran de Twitter.

YSlow es un complemento que se agrega al navegador (Browser) y está disponible para casi todos los navegadores (Firefox, Chrome, Safari, Opera, etc.) menos para Microsoft Internet Explorer.

URL: http://yslow.org/

Página Web de YSlow

Esta herramienta, identifica 34 criterios claves de los cuales actualmente usa 23 criterios para medir la performance de la página, los cuales se muestran en la siguiente figura.

Criterios para Medir Performance de YSlow V2.0

2.2. PageSpeed Insights

Esta herramienta desarrollada por Google en el 2013, inicialmente estaba disponible como una extensión para los navegadores, pero actualmente está disponible como una página web dentro del sitio de desarrolladores de Google.

Una de las ventajas de esta herramienta es que analiza la performance tanto para Desktop como para dispositivos móviles.

URL: https://developers.google.com/speed/pagespeed/insights/

Página Web de PageSpeed Insights

2.3. WebPageTest

Es una herramienta inicialmente desarrollada por AOL en el 2008 y actualmente mantenida por Google. 

Es una de las más usadas actualmente ya que muestra información completa de todas las métricas de performance vistas anteriormente.

URL: http://www.webpagetest.org/

Página Web de WebPageTest

3. Página de Prueba: Login del Sistema

Para las pruebas con las 3 herramientas hemos tomado la página de login de un sistema ubicado en la siguiente dirección.

URL: http://red.hteperu.com/test/Incentivos.Appweb/

Página Web de Prueba

Solo hay que resaltar que la página está en ASP.NET MVC y se compone de lo siguiente:
  • 1 archivo html para la página
  • 1 archivo de hoja de estilo: Login.css
  • 2 archivos de JavaScript: md3.js y Login.js
  • 2 archivos de fuentes: regular.woff y regular.woff2
Las pruebas se harán usando Google Chrome V46.0.2490.86 m (64 bits)

4. Pruebas de Performance usando YSlow

Después de descargar el complemento YSlow V2.0 abrir la herramienta y realizar los siguientes pasos:
  • Ir a la dirección URL: http://red.hteperu.com/test/Incentivos.Appweb/.
  • Clic al botón “Run Test” de la ficha “Home” similar a lo mostrado en la figura.
Ficha Inicio de YSlow V2.0

  • Automáticamente se irá a la ficha “Grade” similar a lo mostrado en la figura.
Ficha Grado de YSlow V2.0

  • En esta ficha se aprecia el puntaje obtenido por la página, en este caso “93 puntos” obteniendo el grado “A” que significa un buen resultado.
  • Para mejorar el puntaje necesitamos usar CDN (grado C), usar cabeceras de expiración (grado E), configurar Entity Tags (grado D).
  • Si deseamos ver el detalle por tipo de archivos seleccionamos la ficha “Components” y se mostrará algo similar a la siguiente figura.
Ficha Componentes de YSlow V2.0
  • En la figura notamos que aparece un mensaje de color rojo indicando que No se encuentra el archivo favicon (icono de la página web).
  • Si deseamos ver una estadística de archivos por tipos seleccionamos la ficha “Statistics” y se mostrará algo similar a la siguiente figura.
Ficha Estadística de YSlow V2.0

Finalmente, en esta ficha podemos darnos cuenta de que solo se está guardando en cache los archivos de hojas de estilos (css) y de JavaScript (js) pero no la página principal y el icono de inicio (ya que éste no existe).

En términos generales, diremos que hemos pasado la prueba de performance usando YSlow V2.0 de Yahoo.
5. Pruebas de Performance usando PageSpeed Insights

Para realizar las pruebas con esta herramienta realizar los siguientes pasos:
  • Ir a la dirección URL: 
https://developers.google.com/speed/pagespeed/insights/.
  • Ingresar la dirección de la página web con el login:
http://red.hteperu.com/test/Incentivos.Appweb/
  • Clic al botón “Analize” tal como se muestra en la siguiente figura.
Página principal de PageSpeed Insights
  • Automáticamente aparecerá los resultados de la ficha “Mobile” que tiene 2 partes: Velocidad y Experiencia de Usuario.
  • A continuación se muestra un gráfico con la sección de “Velocidad” de la ficha “Mobile”.

Sección Velocidad de la ficha Mobile de PageSpeed Insights

  • Aquí se aprecia que se ha fallado en 2 reglas y se ha pasado 8 reglas. Los 2 temas a mejorar son cargar asíncronamente el archivo CSS y el otro es usar cabeceras de expiración para guardar en cache los archivos JS y CSS.
  • A continuación se muestra un gráfico con la sección de “Experiencia de Usuario” de la ficha “Mobile”.
Sección Experiencia de Usuario de la ficha Mobile de PageSpeed Insights
  • En esta se aprecia que no hay ningún problema de experiencia de usuario si la página se ve en un dispositivo móvil.
  • Si cambiamos a la ficha “Desktop” ésta tiene solo la parte de Velocidad que es exactamente la misma que la de la ficha Mobile.
  • A continuación se muestra un gráfico con la sección de “Velocidad” de la ficha “Desktop”.
Sección Velocidad de la ficha Desktop de PageSpeed Insights
  • En términos generales, podemos decir que también hemos pasado la prueba de performance usando PageSpeed Insights de Google.
6. Pruebas de Performance usando WebPageTest

Para realizar las pruebas con esta herramienta realizar los siguientes pasos:
  • Ir a la dirección URL: 
http://www.webpagetest.org/.
  • Ingresar la dirección de la página web con el login:
http://red.hteperu.com/test/Incentivos.Appweb/
  • Clic al botón “Start Test” tal como se muestra en la siguiente figura.
Página principal de WebPageTest
  • Aparece un mensaje de probando (Testing) y luego se muestra el resultado del test similar al de la siguiente figura.
Página de Resultado de la Prueba en WebPageTest
  • Nuevamente apreciamos que la página web está casi bien excepto que debe usar Cache para archivos JS y CSS (F) y usar CDN (X).
  • Podemos analizar la primera ficha “Summary” que muestra un resumen con una tabla con los tiempos de carga y un par de gráficos con la primera vista y la vista repetida, similar a la siguiente figura.
Ficha Resumen del Resultado de WebPageTest
  • La segunda ficha “Details” muestra mayor detalle de los tiempos de carga, un gráfico de cascada, un gráfico de conexiones y una tabla con las solicitudes realizadas por la página.
  • El gráfico de cascada o “Waterfall View” muestra los tiempos de carga por cada recurso de la página, similar a la siguiente figura.
 Vista Cascada de la Ficha Detalle del Resultado de WebPageTest
  • El gráfico de conexión o “Connection View” muestra los tiempos de carga por conexiones realizadas al servidor, similar a la siguiente figura.
Vista Conexión de la Ficha Detalle del Resultado de WebPageTest
  • Finalmente en la sección de Detalles la tabla “Request Details” muestra los detalles de las solicitudes realizadas por la página, similar a la siguiente figura.
Detalles de Solicitud de la Ficha Detalle del Resultado de WebPageTest
  • Las filas pintadas de color rojo indican peligro, en este caso, el archivo de fuentes woff2 no ha sido registrado en el servidor como extensión conocida (MIME) y el otro problema es que la página no cuenta con un icono de inicio.
  • La tercera ficha “Performance Review” permite mostrar una revisión de las métricas de performance, para lo cual presenta una tabla con la lista de verificación a mejorar, el detalle y un glosario.
Lista de verificación de la Ficha Revisión del Resultado de WebPageTest
  • En el “CheckList” se aprecia claramente los temas que se pueden mejorar (color rojo), el archivo de fuente woff2 y el archivo de icono, además de usar caché para contenido estático (CSS, JS) y usar un servidor CDN.
Detalles de la Ficha Revisión del Resultado de WebPageTest

Glosario de la Ficha Revisión del Resultado de WebPageTest
  • La cuarta ficha “Content Breakdown” permite desglosar el contenido por tipo de recurso, mostrando 4 gráficos: por tipo MIME y por Conexión, tanto para la primera vista como para las vistas repetidas.
Gráfico por Tipo MIME (Primera Vista) de la Ficha Desglosar Contenido del Resultado de WebPageTest

Gráfico por Conexión (Primera Vista) de la Ficha Desglosar Contenido del Resultado de WebPageTest

Gráfico por Tipo MIME (Vista Repetida) de la Ficha Desglosar Contenido del Resultado de WebPageTest

Gráfico por Conexión (Vista Repetida) de la Ficha Desglosar Contenido del Resultado de WebPageTest
  • La quinta ficha “Domains” muestra 2 gráficos de desglose de contenido pero por dominio, tanto para la primera vista como para las vistas repetidas.
  • Solo hay que mencionar que No es necesario tenar varios Dominios (incluyendo CDN) cuando el número de archivos es poco, por ejemplo en nuestro caso, la página de login tiene solo 6 archivos.
  • A continuación se muestra los gráficos de la ficha “Domains” conteniendo el desglose de contenidos para la primera vista y para las vistas repetidas.
Gráfico de desglose de contenido (Primera Vista) de la Ficha Dominio del Resultado de WebPageTest
Gráfico de desglose de contenido (Vista Repetida) de la Ficha Dominio del Resultado de WebPageTest

  • Finalmente, revisaremos la sexta y última ficha llamada “Screen Shot” que muestra 2 gráficos con las pantallas de la página totalmente cargada y otra con el Documento Completado, además también los mensajes de consola del Log.
  • A continuación se muestra los gráficos de la ficha “Screen Shot” y los mensajes del Log.
Gráfico de la Pantalla Totalmente Cargada de la Ficha Captura de Pantalla del Resultado de WebPageTest
Gráfico de la Pantalla con Documento Completado de la Ficha Captura de Pantalla del Resultado de WebPageTest
Gráfico de Log de la Ficha Captura de Pantalla del Resultado de WebPageTest

  • En términos generales, podemos decir que también hemos pasado la prueba de performance usando WebPageTest de Google.
Finalmente, si hacemos caso de las sugerencias de estas 3 herramientas de performance nuestro sitio será muy rápido.

Descarga del documento completo
Pruebas_Performance