Decimodan
September 29, 2019

Creando una Progressive Web App desde cero con VueJS - Parte 1

Poco a poco la brecha entre las aplicaciones móviles nativas y las aplicaciones web se va “cerrando” hasta llegar al punto donde las Progressive Web Apps (PWAs) están tomando parte del mercado mainstream.

En 2018 muchas empresas se enfocaron en adaptarse a esta tendencia tales como: Uber, Starbucks, Pinterest, etc. y ya tienen creadas sus PWAs de forma paralela a sus aplicaciones móviles.

Las razones son obvias y algunos ejemplos son impresionantes; tal es el caso de Trivago que nos muestra un impresionante 97% de incremento en sus conversiones, entonces…

¿Por qué deberíamos iniciar a desarrollar PWAs ahora?

2018 fue el año donde la mayoría de las empresas que desarrollan navegadores web empezaron a apoyar la tecnología detrás de los PWAs. Particularmente hablando, Microsoft nos dice que está comprometida en llevar las PWAs** a mas de 500 millones de dispositivos corriendo Windows 10. Por otro lado, Google se aventuró a llamarlo “el futuro del desarrollo de aplicaciones”, por eso vemos como herramientas como Lighthouse, encargada de mejorar la calidad de las páginas web, ahora “audite” el concepto de PWA por igual que el SEO o la accesibilidad.

Finalmente, Apple, ha empezando a aceptar que las PWA son claramente una amenaza al modelo de negocios del Apple App Store.

Este articulo es el primero de la serie que enseñará como desarrollar una PWA desde cero con VueJS

Parte 1: Cómo crear una Calculadora con VueJS.

Parte 2: Haciendo que nuestra aplicación trabaje Offline

Nuestra calculadora

La calculadora que vamos a construir en este tutorial

La calculadora que vamos a construir en este tutorial

Creo que iniciar con una calculadora es muy sencillo debido a que muchas universidades utilizan este ejemplo para iniciarse en algunos lenguajes de programación.

Usaremos VueJS para este tutorial debido a que viene con un gran template que hace mucho más fácil iniciar con un proyecto para una PWA. Otras razones por las que fue elegido, pueden encontrarse aquí.

Resumen de herramientas a utilizar:

Puedes bajar el proyecto desde Github si prefieres o seguir el tutorial a continuación.

Creando el esqueleto del proyecto

Iniciaremos desde una estructura básica de carpetas para nuestra aplicación. Para acelerar un poco las cosas utilizaremos vue-cli. Vamos a instalarlo de forma global.

npm install -g @vue/cli

Ahora vamos a utilizar el siguiente template:

vue init pwa calculadora

Nos aparecerá una serie de opciones a elegir, se recomienda la siguiente configuración:

? Project name calculadora
? Project short name: fewer than 12 characters to not be truncated on homescreen
s (default: same as name) calculadora
? Project description Una calculadora simple creada con VueJS
? Author Daniel Guerrero <https://decimodan.com>
? Vue build standalone
? Install vue-router? No
? Use ESLint to lint your code? No
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No

No agregamos la parte de test unitarios para hacer más breve este articulo, pero si vas a hacer un proyecto productivo deberías de agregarlo.

Siguiente, vamos a agregar las dependencias necesarias para el proyecto, eso lo hacemos de la siguiente manera:

npm install

Por ahora no hay que confundirse con la mayoría de archivos en el proyecto, ya que no modicaremos la mayoría de ellos. Si deseas aprender más de la estructura de este proyecto te recomiendo que revises la documentación oficial.

Solamente quedaría inicializar el proyecto:

npm run dev

Una vez iniciando este proyecto veremos lo siguiente:

Proyecto inicializado

Proyecto inicializado

Este es el árbol de directorios que utilizaremos para este tutorial, está resumido a lo más importante y es el que se crea por defecto:

.
|____build
|____config
|____node_modules
|____src
||____assets
||____components
	- Hello.vue
 App.vue
|____static

Cómo vemos, tenemos 2 componentes principales que conformarán a nuestra aplicación. Para nuestra aplicación necesitaremos solamente 1 componente y ahí realizaremos lo necesario. Para esto, renombraremos el archivo ‘Hello.vue’ por ‘Calculadora.vue’ y lo añadiremos al archivo principal de ‘App.vue’

Es decir, nuestra estructura del proyecto quedará de la siguiente manera:

.
|____build
|____config
|____node_modules
|____src
||____assets
||____components
	- Calculadora.vue
 App.vue
|____static

Y nuestro archivo ‘App.vue’ quedará de la siguiente forma: (le hice unas pequeñas modificaciones al estilo para que marcar el cambio 😌)

<template>
  <div id="app">
    <header>
      <span>PWA - Calculadora - Vuejs</span>
    </header>
    <main>
      <calculadora></calculadora>
    </main>
  </div>
</template>

<script>
import Calculadora from './components/Calculadora'

export default {
  name: 'app',
  components: {
    Calculadora
  }
}
</script>

<style>
body {
  margin: 0;
  background: black;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}

main {
  text-align: center;
  margin-top: 40px;
}

header {
  margin: 0;
  height: 56px;
  padding: 0 16px 0 24px;
  background-color: #35495E;
  color: #ffffff;
  text-align: center;
}

header span {
  display: block;
  position: relative;
  font-size: 20px;
  line-height: 1;
  letter-spacing: .02em;
  font-weight: 400;
  box-sizing: border-box;
  padding-top: 16px;
}
</style>

Con todo esto nuestra aplicación se verá así:

Proyecto inicializado

Proyecto inicializado

Creando la interface

Manos a la obra ahora si, vamos a modificar el archivo ‘Calculadora.vue’ con lo siguiente:

<template>
    <div class="calculadora" onselectstart='return false'>
        <div class="resultado">{{resultado}}</div>
        <div @click="borrar()" class='btn oscuro'>C</div>
        <div @click="signo()" class='btn oscuro'>+/-</div>
        <div @click="porcentaje()" class='btn oscuro'>%</div>
        <div @click="dividir()" class='btn operador'>/</div>
        <div @click="agregar(7)" class='btn'>7</div>
        <div @click="agregar(8)" class='btn'>8</div>
        <div @click="agregar(9)" class='btn'>9</div>
        <div @click="multiplicar()" class='btn operador'>*</div>
        <div @click="agregar(4)" class='btn'>4</div>
        <div @click="agregar(5)" class='btn'>5</div>
        <div @click="agregar(6)" class='btn'>6</div>
        <div @click="restar()" class='btn operador'>-</div>
        <div @click="agregar(1)" class='btn'>1</div>
        <div @click="agregar(2)" class='btn'>2</div>
        <div @click="agregar(3)" class='btn'>3</div>
        <div @click="sumar()" class='btn operador'>+</div>
        <div @click='agregar(0)' class='btn cero btn-abajo'>0</div>
        <div @click='puntoDecimal()' class='btn btn-abajo'>.</div>
        <div @click='igual()' class='btn operador btn-abajo'>=</div>
    </div>
</template>

Como vemos solamente agregamos el marcado que nos ayudará a crear la interface, además, agregamos las funciones necesarias para poder hacer las funcionalidades que la calculadora necesita… Terminando esto nuestra aplicación debería verse así:

Calculadora todavía sin estilos

Calculadora todavía sin estilos

Como vemos, se ve de una forma algo rara… Así que vamos a arreglar eso…

Nuevamente nos vamos al archivo ‘Calculadora.vue’ y modificamos la parte del estilo agregando lo siguiente:

style>
body {
  margin: 0;
  background-color: black;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}

main {
  text-align: center;
  margin-top: 40px;
}

header {
  margin: 0;
  height: 56px;
  padding: 0 16px 0 24px;
  background-color: #35495E;
  color: #ffffff;
  text-align: center;
}

header span {
  display: block;
  position: relative;
  font-size: 20px;
  line-height: 1;
  letter-spacing: .02em;
  font-weight: 400;
  box-sizing: border-box;
  padding-top: 16px;
}
</style>

Este estilo convertirá lo que teníamos antes, a esto: (también borré el logo de VueJS por que ya no tenía mucho sentido dejarlo…)

El estilo de nuestra calculadora

El estilo de nuestra calculadora

Creando la funcionalidad

Usaremos Javascript para esto, en esta parte agradezco bastante a **Rose ** que me ayudó a encontrar y resolver algunos bugs que fuimos encontrando en el camino 😅). Entramos nuevamente al archivo ‘Calculadora.vue’ y añadimos lo siguiente:

<script>
export default {
  data () {
    return {
      resultado: 0,
      operadorClick: false,
      operador: null,
      anterior: null,
      puntito: false
    }
  },
  methods: {
    borrar () {
      this.resultado = 0
    },
    signo () {
      this.resultado =
        this.resultado < 0
          ? (this.resultado = this.resultado - this.resultado * 2)
          : (this.resultado = this.resultado - this.resultado * 2)
    },
    porcentaje () {
      this.resultado = this.resultado / 100
    },
    agregar (numero) {
      if (this.operadorClick && !this.puntito) {
        this.resultado = numero
        this.operadorClick = false
      } else {
        if (this.operadorClick && this.puntito) {
          this.resultado = '' + this.resultado + numero
          this.puntito = false
          this.operadorClick = false
        } else {
          this.resultado =
          this.resultado === 0
            ? (this.resultado = numero)
            : '' + this.resultado + numero
        }
      }
    },
    puntoDecimal () {
      if (this.operadorClick) {
        this.resultado = '0.'
        this.puntito = true
      }
      if (/\d+\.+/g.test(this.resultado)) {
      } else {
        this.resultado = this.resultado + '.'
      }
    },
    dividir () {
      this.operador = (a, b) => a / b
      this.anterior = this.resultado
      this.operadorClick = true
    },
    multiplicar () {
      this.operador = (a, b) => a * b
      this.anterior = this.resultado
      this.operadorClick = true
    },
    restar () {
      this.operador = (a, b) => a - b
      this.anterior = this.resultado
      this.operadorClick = true
    },
    sumar () {
      this.operador = (a, b) => a + b
      this.anterior = this.resultado
      this.operadorClick = true
    },
    igual () {
      this.resultado = this.operador(Number(this.anterior), Number(this.resultado))
      this.anterior = null
      this.operadorClick = true
    }
  }
}
</script>

Este código todavía se puede optimizar, pero creo que muestra bastante de la funcionalidad y así es bastante más fácil de entender… Una vez agregando esto podremos observar lo siguiente:

Nuestra calculadora funcionando

Nuestra calculadora funcionando

Auditando nuestra aplicación

Ahora que ya tenemos algo funcionando pasaremos a la auditoría de nuestra aplicación y para ello utilizaremos Lighthouse que funciona perfecto cómo extensión en Chrome. El reporte inicial que obtenemos de esta aplicación con Lighthouse es el siguiente:

Reporte inicial de Lighthouse para nuestra aplicación

Reporte inicial de Lighthouse para nuestra aplicación

Por lo que vemos aquí todavía tenemos mucho que mejorar, para ello, necesitamos crear nuestro aplicativo para producción, eso lo haremos de la siguiente forma:

npm run build

Finalmente, cuando este proceso termine necesitaremos verlo, una forma práctica de verlo es con la herramienta serve de NodeJS, por lo que pasaremos a instalarlo de la siguiente forma:

npm install -g serve

Y procedemos a utilizarlo para ’levantar’ nuestro aplicativo de producción, esto se hace de la siguiente forma:

serve dist

Con esto se levantará por defecto un servidor en el puerto 5000 donde podremos ver nuestra aplicación funcionando, ahora usaremos nuevamente Lighthouse para ver si hubo algún cambio:

Reporte inicial de Lighthouse

Reporte de Lighthouse usando el modo producción

Como vemos, el cambio es bastante… Lo que hizo a grandes rasgos fue minificar los archivos html, css y js, lo que permitió mejorar casi en 5x el rendimiento de nuestra aplicación en términos de performance, por lo que recomiendo siempre utilizar este modo para producción.

¿Entonces ya tengo mi PWA?

Respuesta corta: NO

¿Entonces?

Nos falta considerar una serie de cosas para poder considerar a nuestra aplicación una verdadera PWA, cómo son:

Todo eso lo veremos en los siguientes artículos, debido a que se necesitan abordar otros temas más a detalle… Lo bueno que era una simple calculadora…

Conclusiones

Como vimos, ya pudimos iniciar nuestra PWA desde cero utilizando VueJS y con esto ya podemos irnos familiarizando con el concepto, además, vimos que utilizar este framework nos ayuda un poco con la curva de aprendizaje técnica (por que ya vimos que no son sólo cuestiones del código lo que hay que aprender)…

Les dejo el código de la aplicación: Código

Y les dejo algunos artículos que les podrían ayudar a profundizar más acerca de ciertos temas vistos aquí:

Y eso es todo. Saludos a todos!

Contáctame

O simplemente mándame un saludo 🙈