Crear apps multiplataforma con JavaScript y Capacitor

Si sabes programar aplicaciones web HTML5, ya puedes empezar a crear apps multiplataforma con JavaScript y la librería Capacitor.

https://capacitorjs.com/ A cross-platform native runtime for web apps.
Crear apps multiplataforma con JavaScript y Capacitor
Esquema de la funcionalidad de Capacitor

¿Quieres meterte manos a la obra ya con Capacitor? Saltar directamente al tutorial

Actualización: En este artículo aprenderás a crear apps multiplataforma para dispositivos móbiles Android e iOS. Si también te interesa crear aplicaciones para Windows, MacOSX o Linux, a continuación te dejo un enlace a la segunda parte:

Crear aplicaciones de escritorio con JavaScript y Tauri

Características de las apps híbridas

Desde el inicio de este humilde blog, hemos estado viendo librerías JavaScript que, de algún modo u otro, nos ayudaban en nuestro dia a dia como programadores.

Hemos visto librerías que cubren necesidades de UX/UI, como la librería que vimos para crear un sistema de etiquetas.

Crear un sistema de tags con JavaScript y Tagify

Otras que permiten trabajar con conceptos complejos de forma simplificada. Y hasta librerías para expresar nuestra creatividad.

Todas ellas comparten algo en común, se usan durante la fase de desarrollo. Generalmente, se importan como dependencias de nuestro código, y cubren algunas funcionalidades del proyecto.

Sin embargo, hoy veremos una herramienta que se ubica en otra fase de la producción. En esta ocasión nos centraremos en la compilación y distribución de las aplicaciones.

En concreto, veremos cómo crear una aplicación a partir de código HTML5, y que se pueda instalar en dispositivos móviles Android o iOS.

Si, lo has leído bien, gracias a la librería CapacitorJs es posible crear apps con lenguajes de desarrollo web, y distribuirlas en Google Play y App Store.

CapacitorJs, fue creada por el equipo de Ionic, y es ampliamente mantenida, y usada por una comunidad enorme de desarrolladores. 

A grandes rasgos, se trata de una herramienta que permite “empaquetar” un conjunto de archivos HTML/CSS/JS dentro de una aplicación para Android o iOS. 

Posteriormente, la aplicación carga esos archivos en un navegador interno llamado WebViewer, y muestra su contenido a pantalla completa.

Este planteamiento tecnológico se conoce como aplicación híbrida, y ya se empezó a trabajar en el año 2008 con una librería llamada Phonegap. 

A efectos prácticos, el usuario no nota diferencias significativas respecto a las apps nativas. Sin embargo, hay ciertas consideraciones a tener en cuenta a la hora de desarrollar este tipo de apps. 

No te preocupes, las iremos detallando detenidamente a continuación.

Las alternativas a Capacitor

En primer lugar, es importante ser consciente de que existen alternativas a Capacitor que quizá se ajusten más a tus necesidades.

Para ello deberías preguntarte qué clase de aplicación quieres crear, y comprobar si Capacitor es la mejor herramienta para tí.

Para tratar de ayudarte en esa tarea, he preparado el siguiente esquema. En él tienes que responderte preguntas acerca de tu app. Idealmente, al final sabrás qué tecnología se ajusta más según tus intereses.

Ojo, este esquema no es una verdad absoluta. Solo una simple guía elaborada a partir de mi propia experiencia y conocimiento.

esquema para decidir si Capacitor se ajusta a tu proyecto
Haz click sobre la imagen para verla a tamaño completo

Si sigues aquí significa que Capacitor es una opción viable para tí, genial!. Vamos a ponernos manos a la obra, pues.

Por cierto, si te ha quedado alguna duda en relación a la diferencia entre Flutter, React Native y Capacitor, no te preocupes. Pronto publicaremos un artículo con una comparativa, e incluso implementaremos un ejercicio con ambas. Así que sigue atento a las futuras publicaciones.

Crear y compilar apps multiplataforma con JavaScript y Capacitor

El siguiente paso es preparar el entorno necesario para crear aplicaciones híbridas multiplataforma.

Capacitor por sí solo no puede generar paquetes .apk o .ipa, estos, son los archivos instaladores de apps para Android y iOS respectivamente. Por eso, es imprescindible disponer de los programas que realizan la compilación. 

Estos softwares son Android Studio y Xcode, te dejo los enlaces a continuación.

https://developer.android.com/studio Enlace a Android Studio

https://apps.apple.com/es/app/xcode/id497799835 Enlace a Xcode (solo para sistemas MacOS)

Ambos programas permiten instalar emuladores para testear apps antes de distribuirlas. Asegúrate de instalar al menos un dispositivo virtual si quieres probar tu aplicación directamente en el ordenador.

Una vez tengas estas herramientas correctamente instaladas y configuradas, ya estás en disposición de crear una aplicación híbrida.

Tal y como hemos comentado, el “core” de la app puede ser cualquier proyecto frontend web. De modo que, empezaremos programando una aplicación como si de una webapp convencional se tratara. 

Por supuesto, puedes apoyarte en el framework que quieras. En mi caso he usado ReactJs, y he creado un gestor de gastos muy simple, al que he llamado “Expense Tracker”. Haz click en la siguiente imagen para ver el resultado final de la aplicación

Captura de pantalla de Expense Tracker
Haz click sobre la imagen para ver el proyecto en marcha

Si quieres centrarte en la creación de la app multiplataforma con Capacitor y saltarte la parte de programación de la webapp, puedes usar el código de “Expense Tracker”.

Lo encontrarás en el repositorio de libreriasjs, dentro del directorio “spent-tracker”.

https://github.com/Danivalldo/libreriasjs/tree/master/spent-tracker

Para no extenderme demasiado, no entraremos a ver el código fuente en detalle. Sin embargo, es importante destacar dos bloques de código importantes para el correcto funcionamiento de la app híbrida. Y que, de algún modo, deberías incluir en tu proyecto también.

Por una parte, en el index.html se deben añadir las siguientes etiquetas meta.

<base href="/" />
<meta
   name="viewport"
   content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<!-- add to homescreen for ios -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Ionic App" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />

Con ellas evitamos que el usuario pueda hacer zoom dentro de la app.

Por otra parte, es aconsejable incluir la siguiente instrucción CSS en el primer elemento del layout.

padding-top: env(safe-area-inset-top);

Esta instrucción generará un margen de seguridad en la parte superior. Es especialmente útil para evitar el solapamiento del “notch” que tienen algunos dispositivos móviles.

El último punto, antes de poder compilar la aplicación, es instalar Capacitor en el proyecto.

Para ello, hay que ejecutar los comandos “npm install @capacitor/core” y “npm install @capacitor/cli –save-dev”.

npm install @capacitor/core
npm install @capacitor/cli --save-dev

Tras unos segundos de espera, ya tendremos las dependencias listas para utilizar.

Ejecutamos el comando “npx cap init” para configurar Capacitor en nuestro proyecto, al hacerlo, tendremos que decidir el nombre y el ID de la aplicación. 

npx cap init

El identificador suele expresarse como la construcción inversa de nuestro dominio, acompañado del nombre de la aplicación. En mi caso com.libreriasjs.spendtracker.

Como verás, se habrá incluido un nuevo archivo en tu proyecto llamado capacitor.config.ts. En él aparecen unas pocas opciones de configuración. Por lo general no hace falta editar nada, pero sí prestar especial atención al parámetro “webDir”.

El parámetro webDir debe hacer referencia al directorio donde se genera el bundle de nuestra webapp. Por eso, es importante que generes ese paquete de archivos bundle y te asegures de que webDir apunta al directorio que los contiene.

import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
  appId: 'com.libreriasjs.spendtracker',
  appName: 'spend-tracker',
  webDir: 'build',
  bundledWebRuntime: false
};
export default config

En mi caso, utilicé “create-react-app” como punto de partida. Por consiguiente, el directorio donde se genera el bundle, tras ejecutar “npm run build”, se llama “build”.

Añadir las plataformas Android y iOS al proyecto

A continuación, tenemos que indicar para qué plataformas vamos a generar las apps. Empezaremos por Android y luego prepararemos iOS. De no hacerlo, no estaríamos hablado de crear apps multiplataforma con JavaScript y Capacitor

Ejecutamos el comando “npm install @capacitor/android” para instalar las dependencias necesarias para plataforma Android.

npm install @capacitor/android

Seguidamente lanzamos el comando “npx cap add android”. Esa instrucción generará un directorio nuevo en el proyecto, llamado android. 

npx cap add android

Este directorio es el que necesita Android Studio para realizar la compilación. De hecho, si ejecutamos “npx cap open android”, debería iniciarse Android Studio automáticamente.

npx cap open android

Una vez delante de la interfaz de Android Studio, seleccionamos un emulador de nuestro listado e iniciamos con el botón de play.

Interfaz de Android Studio con la app funcionando en un emulador
Interfaz de Android Studio con la app funcionando en un emulador

Si todo ha funcionado correctamente, deberías ver tu aplicación funcionando en el dispositivo virtual.

También tienes la opción de conectar tu smartphone o tablet por USB e instalar la aplicación directamente a tu terminal.

Ahora, tan solo queda generar la versión para dispositivos iOS. Los pasos són muy similares, sin embargo, por desgracia, sólo podrás realizarlos si dispones de un ordenador MacOSX. Eso se debe a que Xcode no está disponible para sistemas Windows o Linux.

De igual forma, empezamos incluyendo la plataforma como dependencia. Para ello, lanzamos el comando “npm install @capacitor/ios” y seguidamente “npx cap add ios”.

npm install @capacitor/ios
npx cap add ios

Esta segunda instrucción también generará un directorio específico de la plataforma llamado ios. Como ya te puedes imaginar, para abrir el proyecto con Xcode, ejecutamos “npx cap open ios”.

npx cap open ios

En Xcode, también podemos elegir un emulador y ejecutar la app con el botón de play.

Interfaz de XCode con el emulador en marcha
Interfaz de XCode con el emulador en marcha

Instalar la aplicación en un dispositivo real como por ejemplo, un iPhone también es posible. Sin embargo, es necesario configurar un perfil de desarrollador Apple.

Si has llegado hasta aquí, ¡enhorabuena! acabas de aprender cómo crear apps multiplataforma con JavaScript y Capacitor.

Extender la app con funciones nativas

Pero, puede que llegado a este punto te preguntes: Genial, todo esto está muy bien, ¿Pero qué pasa con las funcionalidades nativas propias de las apps? ¿Cómo puedo, por ejemplo, acceder al listado de contactos? ¿O recibir notificaciones?

No te preocupes, Capacitor ofrece la posibilidad de acceder a estas funcionalidades mediante el uso de plugins. Los plugins son extensiones que amplían la parte de código nativo y exponen una API JavaScript para usarlos en nuestro programa.

Existen plugins oficiales y otros creados por la comunidad. Instalar y usar cualquier extensión de estas, suele ser tan sencillo como ejecutar un comando npm.

Por ejemplo, si quisiéramos acceder a la información del modelo y características del dispositivo, podríamos hacerlo instalando el plugin device.

npm install @capacitor/device

Seguidamente, deberíamos actualizar el proyecto mediante el comando “npx cap sync”. Gracias a esta instrucción, Capacitor se encargará de actualizar todas las plataformas con el código nativo pertinente.

npx cap sync

A partir de ahí, ya podemos utilizar la funcionalidad que nos brinda la extensión mediante su API JavaScript.

import { Device } from '@capacitor/device';
const logDeviceInfo = async () => {
  const info = await Device.getInfo();
  console.log(info);
};
const logBatteryInfo = async () => {
  const info = await Device.getBatteryInfo();
  console.log(info);
};

Este es un ejemplo muy sencillo, sin embargo, implementar la funcionalidad de recibir notificaciones push en el móbil puede resultar algo más complejo. Por suerte, he preparado una guía paso a paso donde te explico como hacerlo. Te animo a que le eches una ojeada.

Recibir notificaciones push con el servicio Cloud Messaging

Habilita la función de “hotreloading” para mejorar la experiencia de desarrollo.

Tarde o temprano, te darás cuenta que andar re-compilando tu aplicación, cada vez que haces un cambio, se vuelve extremadamente tedioso.

Así que deja que te ahorre unas cuantas horas de aburrimiento innecesario, añadiendo la siguiente mejora a tu entorno de trabajo.

Como ya imaginarás, al compilar la aplicación, los archivos HTML / CSS y JS que conforman tu proyecto, se almacenan como parte de la aplicación.

No obstante, también existe la posibilidad de pedirle a Capacitor que cargue estos recursos de un servidor externo, como por ejemplo, un servidor local.

De este modo, puedes aprovechar las capacidades de tu entorno de desarrollo, como por ejemplo la recarga automática o «hotreloading», directamente en la app híbrida. Vamos a ver como.

Edita el archivo “capacitor.config.ts” para incluir la siguiente porción de configuración, justo a continuación de la propiedad “bundledWebRuntime”.

bundledWebRuntime: false,
server:
    process.env.NODE_ENV === "dev"
      ? {
          url: "http://192.168.1.135:3000",
          cleartext: true,
        }
      : undefined,

Con estas instrucciones, le estamos indicando a Capacitor que, si existe la variable de entorno NODE_ENV, cargue el contenido a partir de URL indicada. Asegúrate de que la IP y el puerto coincidan con los de tu red.

Existen muchas formas para conocer la IP asignada a tu máquina, pero si has utilizado “create-react-app”, al lanzar el comando “npm start” verás esa información de forma clara.

Obtener IP de la red local al ejecutar "npm start"
Obtener IP de la red local al ejecutar «npm start»

Ahora, sencillamente edita “package.json” para incluir los siguientes scripts.

"dev-android":"NODE_ENV=dev npm run build && npx cap sync && npx cap open android",
"dev-ios":"NODE_ENV=dev npm run build && npx cap sync && npx cap open ios"

Eso te permitirá compilar apps que obtienen los recursos directamente del servidor local, y por consiguiente, también recargan a tiempo real, al modificarlos con tu editor de código.

Lo cual es excelente para trabajar durante la fase de desarrollo.

Más recursos para seguir aprendiendo

En este artículo me he querido centrar únicamente en la herramienta Capacitor, y no he hablado de la librería de componentes Ionic. En la segunda parte de este post veremos en detalle todas las posibilidades que ofrece.

A continuación te dejo un conjunto de enlaces para complementar un poco más lo aprendido.

Espero que este tutorial te haya resultado útil, si así ha sido, te agradeceria que lo difundieras entre compañeros programadores.

Nos vemos pronto, un abrazo desarrolladores.

Deja un comentario