Vue — Como crear aplicaciones móviles hibridas

Vue — Como crear aplicaciones móviles hibridas

En este post vamos a ver paso a paso como crear una aplicación móvil híbrida utilizando Apache Cordova y Vue.js 2.

Los pasos que verás a continuación, describen el proceso de configuración de una plataforma de desarrollo en la que podrás crear aplicaciones móviles híbridas utilizando Cordova + Vue.js 2

Esto incluye:

  • Instalación y configuración de Cordova + Webpack + Vue.js.

  • Vista previa de la aplicación en el navegador.

  • Hot / Live: Recarga tu aplicación en el navegador automáticamente al detectar nuevos cambios.

  • Ejecutar la aplicación en dispositivos móviles Android / iOS (Utilizaremos los emuladores respectivos).

Antes de empezar, debo definirles lo que es una aplicación móvil hibrida:

¿Qué es una aplicación móvil híbrida?

Las aplicaciones híbridas son aplicaciones móviles diseñadas en un lenguaje de programación web empleando tecnologías como HTML5, CSS y JavaScript, y que gracias a un framework (en nuestro caso Cordova), permite adaptar la vista de nuestra aplicación web a cualquier vista de un dispositivo móvil mediante un navegador empotrado ( WebView).

Adicionalmente, este framework ( Cordova), mediante plugins, nos permite acceder a los componentes nativos de los dispositivos tales como la cámara, GPS, Wifi, Acelerómetros, Libreta de Contactos, entre otros.

Lo interesante de todo esto es que cada día el look and feel de una aplicación híbrida es casi igual al de una nativa, esto gracias a que poco a poco esta tecnología ha ido madurando y haciendo que sea más fácil integrar estas aplicaciones en los dispositivos móviles.

Otro aspecto importante es que estas aplicaciones híbridas se distribuyen igual que una nativa, mediante los markets como Google Play Store y el App Store.

Y por último y no menos importante está el hecho de que las aplicaciones híbridas brindan ventajas notables frente a las nativas, algunas de estas son:

  • El costo de desarrollo es muchisimo inferior al de una aplicación nativa ya que el código se escribe una sola vez y es compilado hacia las distintas plataformas deseadas.

  • No se requiere de sólidos conocimientos nativos para cada plataforma ya que la curva de aprendizaje y de implementación es muy corta.

  • El mantenimiento de nuestras aplicaciones es muchisimo mas eficiente ya que solo tenemos que cambiar el código una sola vez y luego compilar hacia las distintas plataformas.

  • No se requiere conocimiento de lenguajes de programación natívos como Java (Android), Swift u Objective C (iOS), entre otros.

Pre-Requisitos

Para llevar a cabo este ejemplo, debemos tener instalado los siguientes pre-requisitos:

  • Sistema Operativo macOS — High Sierra 10.13.2

  • Node.js — v9.2.1-Ir a la web oficial para instalar Node.js

  • Apache Cordova — 8.0.0 — npm install -g cordova

  • Vue-CLI — 2.9.3 — npm install-g vue-cli

  • Gradle — 4.5.1 — brew install gradle — ¿Cómo Instalar Homebrew?

  • Android SDK — brew tap caskroom/cask — brew cask install android-sdk

  • Android Platform Tools — brew cask install android-platform-tools

  • Xcode-xcode-select -install- Descargar Xcode

  • ios-deploy-npm install -g ios-deploy

Iniciando el proyecto con Cordova + Vue.js + Webpack

Antes de todo, debemos situarnos en el path donde deseamos que se cree nuestro proyecto.

  1. Creamos el proyeto Cordova:
# Creating a new cordova project.
cordova create mi-app-hibrida com.franciscougalde.apps
  1. Creamos el proyecto Vue.js + Webpack:
vue init webpack mi-app-hibrida

Vue te preguntará:

? Target directory exists. Continue? (Y/n) **Y**

A lo que debemos contestar “Y” para aceptar y continuar ya que el directorio fué creado y configurado previamente por el proyecto de cordova en el paso anterior.

Seguidamente, vue te pedirá información para configurar el proyecto, los datos que yo introduje son los siguientes:

? Target directory exists. Continue? **Yes**
? Project name **mi-app-hibrida**
? Project description **Mi Aplicación Móvil Hibrida con Cordova + Vue.js 2**
? Author **Francisco Ugalde**
? Vue build **standalone**
? Install vue-router? **Yes**
? Use ESLint to lint your code? **No**
? Set up unit tests **No**
? Setup e2e tests with Nightwatch? **No**
? Should we run `npm install` for you after the project has been created? (recommended) **npm**

vue-cli · Generated "mi-app-hibrida".

# Installing project dependencies ...

# ========================

Unir los procesos de “build” del proyecto Cordova y Vue.js-WebPack

El directorio ./www de tu proyecto Cordova debe lucir actualmente así:

www
├── css
│   └── index.css
├── img
│   └── logo.png
├── index.html
└── js
└── index.js

Lo primero que debemos hacer es eliminar el contenido de la carpeta ./www de Cordova, ya que construiremos este contenido con WebPack en su lugar.

Tendremos que eliminar el directorio ./www ya que este es el código que Cordova integrará en el dispositivo móvil.

cd mi-app-hibrida

sudo rm -r www/*

# Password: ************

Ahora debemos abrir el archivo de configuación de Webpack: ./config/index.js y actualiza los siguientes paths:

  • Cambia los paths de index y **assestsRoot** para apuntar al directorio ./www y así el código de nuestra aplicación se genere en la ruta ./www/dist antes de ser empaquetado en el dispositivo móvil.

  • Cambia el valor del path de **assetsPublicPath **para que sea una cadena vacía. Esto va a permitir a tu móvil servir la vista vía el protocolo file:///. Esto es importante puesto que no estaremos ejecutando un servidor web en nuestro dispositivo móvil (usualmente).

Actualiza tu ./config/index.js para que luzca de la siguiente manera:

build: {
    // Template for index.html
    index: path.resolve(__dirname, '../www/dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../www/dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '',
}

Abre el archivo config.xml en tu IDE preferido y actializa el punto de entrada del WebView de Cordova.

<content src=”dist/index.html” />

Ahora procedemos a crear el paquete de distribución de nuestra aplicación:

npm run build

mi-app-hibrida@1.0.0 build /Users/fjugaldev/Sites/mi-app-hibrida
node build/build.js

Hash: 0faab7ddba58ce23a830
Version: webpack 3.11.0
Time: 16236ms
                                                  Asset       Size  Chunks             Chunk Names
               static/js/vendor.5973cf24864eecc78c48.js     111 kB       0  [emitted]  vendor
                  static/js/app.b22ce679862c47a75225.js    11.6 kB       1  [emitted]  app
             static/js/manifest.2ae2e69a05c33dfc65f8.js  857 bytes       2  [emitted]  manifest
    static/css/app.30790115300ab27614ce176899523b62.css  432 bytes       1  [emitted]  app
static/css/app.30790115300ab27614ce176899523b62.css.map  828 bytes          [emitted]
           static/js/vendor.5973cf24864eecc78c48.js.map     548 kB       0  [emitted]  vendor
              static/js/app.b22ce679862c47a75225.js.map    22.2 kB       1  [emitted]  app
         static/js/manifest.2ae2e69a05c33dfc65f8.js.map    4.97 kB       2  [emitted]  manifest
                                             index.html  516 bytes          [emitted]

Build complete.

Tip: built files are meant to be served over an HTTP server.
  Opening index.html over file:// won't work.

El directorio ./www/dist debe lucir ahora algo parecido a esto:

www
└── dist
    ├── index.html
    └── static
        ├── css
        │   ├── app.30790115300ab27614ce176899523b62.css
        │   └── app.30790115300ab27614ce176899523b62.css.map
        └── js
            ├── app.b22ce679862c47a75225.js|
            ├── app.b22ce679862c47a75225.js.map
            ├── manifest.2ae2e69a05c33dfc65f8.js
            ├── manifest.2ae2e69a05c33dfc65f8.js.map
            ├── vendor.5973cf24864eecc78c48.js
            └── vendor.5973cf24864eecc78c48.js.map

Abre el archivo **./www/dist/index.html** en tu navegador para verificar que todo funciona perfectamente vía el protocolo file:///.

open ./www/dist/index.html

Puedes notar en la barra de dirección el protocolo file:///

Seguidamente debemos abrir el archivo ./index.html de Vue.js en tu IDE y actualiza el meta tag “Content-Security-Policy” para permitir los sockets web locales. Puedes hacer esto agregando: connect-src ‘self’ ws:;. Esto permitirá a Webpack conocer cuando se ha creado el paquete de distribución de la aplicación y cuando se ha recargado o actualizado el codigo en la vista previa del navegador. Esto deberá suceder cada vez que hagas un cambio en el codigo fuente.

<meta http-equiv=”Content-Security-Policy” content=”default-srcselfdata: gap: <a href="[https://ssl.gstatic.com/](https://ssl.gstatic.com/)" target="_blank" rel="nofollow noopener noopener" data-href="[https://ssl.gstatic.com](https://ssl.gstatic.com)" data-mce-href="[https://ssl.gstatic.com/](https://ssl.gstatic.com/)">[https://ssl.gstatic.com](https://ssl.gstatic.com)</a> ‘unsafe-eval’; style-src ‘self’ ‘unsafe-inline’; media-src *; img-src ‘self’ data: content:; connect-src ‘self’ ws:;”>

Ahora podemos probar que el modo dev funciona correctamente:

npm run dev

mi-app-hibrida@1.0.0 dev /Users/fjugaldev/Sites/mi-app-hibrida

webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

95% emitting

DONE  Compiled successfully in 8968ms                                                                                                            1:37:22 AM

I  Your application is running here: http://localhost:8080

Ahora el Servidor hot-reload de Vue-Webpack esta online, Entra en http://localhost:8080 para ver la aplicación.

Deberas ver la siguiente pantalla:

Nótese el mensaje de web-sockets en el log de la consola, y el host:puerto en la barra de direcciones del navegador.

Ejecutando la aplicación en Android

Vamos ahora a probar que todo funciona en un dispositivo móvil Android. Asegurate que tienes conectado uno en tu computador.

Procedemos a agregar a Android como plataforma en Cordova:

cordova platform add android


Using cordova-fetch for cordova-android@~7.0.0
Adding android project...
Creating Cordova project for the Android platform:
Path: platforms/android
Package: com.franciscougalde.apps
Name: HelloCordova
Activity: MainActivity
Android target: android-26
Subproject Path: CordovaLib
Subproject Path: app
Android project created with cordova-android@7.0.0
Android Studio project detected
Android Studio project detected

Discovered plugin "cordova-plugin-whitelist" in config.xml. Adding it to the project

Installing "cordova-plugin-whitelist" for android

This plugin is only applicable for versions of cordova-android greater than 4.0. If you have a previous platform version, you do *not* need this plugin since the whitelist will be built in.

Adding cordova-plugin-whitelist to package.json

Saved plugin info for "cordova-plugin-whitelist" to config.xml

--save flag or autosave detected

Saving android@~7.0.0 into config.xml file ...

Luego de esto procedemos a ejecutar la aplicación en nuestro dispositivo Android:

cordova run android

Android Studio project detected

ANDROID_HOME=/usr/local/Caskroom/android-sdk/3859397

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home

studio

Subproject Path: CordovaLib

Subproject Path: app

publishNonDefault is deprecated and has no effect anymore. All variants are now published.

The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.

at build_8u9efqela5ohwabjwm0tr50nm.run(/Users/fjugaldev/Sites/mi-app-hibrida/platforms/android/app/build.gradle:143)

:CordovaLib:preBuild UP-TO-DATE
:CordovaLib:preDebugBuild UP-TO-DATE
:CordovaLib:compileDebugAidl UP-TO-DATE
:CordovaLib:compileDebugRenderscript UP-TO-DATE
:CordovaLib:checkDebugManifest UP-TO-DATE
:CordovaLib:generateDebugBuildConfig UP-TO-DATE
:CordovaLib:prepareLintJar UP-TO-DATE
:CordovaLib:generateDebugResValues UP-TO-DATE
:CordovaLib:generateDebugResources UP-TO-DATE
:CordovaLib:packageDebugResources UP-TO-DATE
:CordovaLib:platformAttrExtractor UP-TO-DATE
:CordovaLib:processDebugManifest UP-TO-DATE
:CordovaLib:processDebugResources UP-TO-DATE
:CordovaLib:generateDebugSources UP-TO-DATE
:CordovaLib:javaPreCompileDebug UP-TO-DATE
:CordovaLib:compileDebugJavaWithJavac UP-TO-DATE
:CordovaLib:processDebugJavaRes NO-SOURCE
:CordovaLib:transformClassesAndResourcesWithPrepareIntermediateJarsForDebug UP-TO-DATE
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:compileDebugAidl UP-TO-DATE
:CordovaLib:packageDebugRenderscript NO-SOURCE
:app:compileDebugRenderscript UP-TO-DATE
:app:checkDebugManifest UP-TO-DATE
:app:generateDebugBuildConfig UP-TO-DATE
:app:prepareLintJar UP-TO-DATE
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources UP-TO-DATE
:app:mergeDebugResources UP-TO-DATE
:app:createDebugCompatibleScreenManifests UP-TO-DATE
:app:processDebugManifest UP-TO-DATE
:app:splitsDiscoveryTaskDebug UP-TO-DATE
:app:processDebugResources UP-TO-DATE
:app:generateDebugSources UP-TO-DATE
:app:javaPreCompileDebug UP-TO-DATE
:app:compileDebugJavaWithJavac UP-TO-DATE
:app:compileDebugNdk NO-SOURCE
:app:compileDebugSources UP-TO-DATE
:CordovaLib:mergeDebugShaders UP-TO-DATE
:CordovaLib:compileDebugShaders UP-TO-DATE
:CordovaLib:generateDebugAssets UP-TO-DATE
:CordovaLib:mergeDebugAssets UP-TO-DATE
:app:mergeDebugShaders UP-TO-DATE
:app:compileDebugShaders UP-TO-DATE
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets UP-TO-DATE
:app:extractTryWithResourcesSupportJarDebug UP-TO-DATE
:app:transformClassesWithStackFramesFixerForDebug UP-TO-DATE
:app:transformClassesWithDesugarForDebug UP-TO-DATE
:app:transformClassesWithDexBuilderForDebug UP-TO-DATE
:app:transformDexArchiveWithExternalLibsDexMergerForDebug UP-TO-DATE
:app:transformDexArchiveWithDexMergerForDebug UP-TO-DATE
:CordovaLib:compileDebugNdk NO-SOURCE
:CordovaLib:mergeDebugJniLibFolders UP-TO-DATE
:CordovaLib:transformNativeLibsWithMergeJniLibsForDebug UP-TO-DATE
:CordovaLib:transformNativeLibsWithIntermediateJniLibsForDebug UP-TO-DATE
:app:mergeDebugJniLibFolders UP-TO-DATE
:app:transformNativeLibsWithMergeJniLibsForDebug UP-TO-DATE
:app:processDebugJavaRes NO-SOURCE
:app:transformResourcesWithMergeJavaResForDebug UP-TO-DATE
:app:validateSigningDebug
:app:packageDebug UP-TO-DATE
:app:assembleDebug UP-TO-DATE
:app:cdvBuildDebug UP-TO-DATE

BUILD SUCCESSFUL in 2s

47 actionable tasks: 1 executed, 46 up-to-date

Built the following apk(s):

/Users/fjugaldev/Sites/mi-app-hibrida/platforms/android/app/build/outputs/apk/debug/app-debug.apk

ANDROID_HOME=/usr/local/Caskroom/android-sdk/3859397

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home

No target specified, deploying to device '634034256815'.

none

Skipping build...

Built the following apk(s):

/Users/fjugaldev/Sites/mi-app-hibrida/platforms/android/app/build/outputs/apk/debug/app-debug.apk

Using apk: /Users/fjugaldev/Sites/mi-app-hibrida/platforms/android/app/build/outputs/apk/debug/app-debug.apk

Package name: com.franciscougalde.apps

LAUNCH SUCCESS

Luego de esto deberás ver la aplicación corriendo en tu dispositivo Android.

Ejecutando la aplicación en iOS

Es tiempo de verificar cosas en un dispositivo iOS. Asegúrate de que lo hayas conectado a tu computador.

Primero, Agreguemos la plataforma iOS a nuestro proyecto Cordova:

cordova platform add ios

Using cordova-fetch for cordova-ios@~4.5.4
Adding ios project...
Creating Cordova project for the iOS platform:
Path: platforms/ios
Package: com.franciscougalde.apps
Name: HelloCordova

iOS project created with cordova-ios@4.5.4

Installing "cordova-plugin-whitelist" for ios

--save flag or autosave detected

Saving ios@~4.5.4 into config.xml file ...

Abre el proyecto de nuestra aplicación en el Xcode ejecutando lo siguiente:

Lo siguiente será seleccionar el certificado de Equipo (Team certificate) en el menú desplegable “Build Signing”.

Crear el paquete para iOS.

cordova build ios

Building project: /Users/fjugaldev/Sites/mi-app-hibrida/platforms/ios/HelloCordova.xcworkspace

Configuration: Debug

Platform: device

User defaults from command line:

IDEArchivePathOverride = /Users/fjugaldev/Sites/mi-app-hibrida/platforms/ios/HelloCordova.xcarchive

Build settings from command line:

CONFIGURATION_BUILD_DIR = /Users/fjugaldev/Sites/mi-app-hibrida/platforms/ios/build/device

SHARED_PRECOMPS_DIR = /Users/fjugaldev/Sites/mi-app-hibrida/platforms/ios/build/sharedpch

Build settings from configuration file '/Users/fjugaldev/Sites/mi-app-hibrida/platforms/ios/cordova/build-debug.xcconfig':

CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES

CODE_SIGN_ENTITLEMENTS = $(PROJECT_DIR)/$(PROJECT_NAME)/Entitlements-$(CONFIGURATION).plist

CODE_SIGN_IDENTITY = iPhone Developer

ENABLE_BITCODE = NO

GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1

HEADER_SEARCH_PATHS = "$(TARGET_BUILD_DIR)/usr/local/lib/include" "$(OBJROOT)/UninstalledProducts/include" "$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include" "$(BUILT_PRODUCTS_DIR)"

OTHER_LDFLAGS = -ObjC

SWIFT_OBJC_BRIDGING_HEADER = $(PROJECT_DIR)/$(PROJECT_NAME)/Bridging-Header.h

=== BUILD TARGET CordovaLib OF PROJECT CordovaLib WITH CONFIGURATION Debug ===

Check dependencies

Write auxiliary files

...

** ARCHIVE SUCCEEDED **

Non-system Ruby in use. This may cause packaging to fail.

If you use RVM, please run `rvm use system`.
If you use chruby, please run `chruby system`.

2018-02-01 16:43:32.249 xcodebuild[82807:848721] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path '/var/folders/kw/5t8w91_n6rb0z8b2z2grsj1r0000gn/T/HelloCordova_2018-02-01_16-43-32.247.xcdistributionlogs'.

Exported HelloCordova.xcarchive to: /Users/fjugaldev/Sites/mi-app-hibrida/platforms/ios/build/device

** EXPORT SUCCEEDED **

Procedemos a ejecutar la aplicación en nuestro dispositivo iOS:

cordova run ios

Deberías poder ver la aplicación Vue.js en tu dispositivo iOS tal como se muestra a continuación:

Y ya con esto hemos logrado entonces combinar dos tecnologías ideales para el desarrollo de aplicaciones móviles híbridas de una forma sencilla y que estoy seguro que a muchos de ustedes les va a servir para iniciarse en este mundo de las aplicaciones móviles.

Si gustas revisar el código resultante de nuestra aplicación de ejemplo, puedes clonarlo desde mi repositorio en github.com

Si te gustó este post, ayúdame a que pueda servirle a muchas más personas, compartiendo mis contenidos en tus redes sociales.

Espero que este post haya sido de gran ayuda para ti, y como siempre, cualquier inquietud o duda que tengas, puedes contactarme por cualquiera de las vías disponibles, o dejando tus comentarios al final de este post. También puedes sugerir que temas o post te gustaría leer a futuro.

Did you find this article valuable?

Support Francisco Ugalde by becoming a sponsor. Any amount is appreciated!