Liferay se apunta a la revolución Front-End
Para ser frontend hay que nacer. Realizan un trabajo muy delicado y meticuloso que, hasta hace no mucho era cosa de html, css y javascript. A los backend no nos gusta,no queremos ni ver un css. Este ha sido mi caso. He estado alejada un tiempo de este mundo y ahora no se ni por dónde empezar.
"La aparición de NodeJs, un entorno Javascript pensado para la capa del servidor, ha introducido una manera fácil para los desarrolladores de Javascript de acceder al servidor y de poder crear una API REST. Una API consigue que los desarrolladores interactúen con los datos de la aplicación de un modo planificado y ordenado. Así, podemos decir que en la actualidad, solo con Javascript, puedes crear una aplicación muy completa."
Esto unido a la aparición de frameworks javascript muy populares como React, Angular, Vue.js ... me han hecho darme cuenta de que adaptarme es una necesidad.
En este post voy a intentar explicar las distintas herramientas que proporciona Liferay para adaptar estos frameworks a su modelo.
1. Antecedentes
1.1. Primeras versiones
En las primeras versiones del SDK NPM de Liferay, gradle y npm cooperaban juntos para generar un artefacto que se pudiera desplegar en Liferay. Esta forma de generar el módulo recibió el nombre Bundle 1.0
Se usaba npm para importar los paquetes javascripts y Gradle para generar el artefacto y desplegarlo en el portal.
Al desplegar, el portal usa el módulo Liferay JS Extender ,que está integrado directamente a partir de la versión 7.2.
Una de las funciones de este módulo es registrar los paquetes npm que mi portlet necesita en Liferay AMD Loader.
El Liferay AMD Loader es el encargado de cargar los paquetes javascript en Liferay.
Cuando un usuario a través del navegador llama al módulo que hemos desarrollado, se genera el html y el javascript, que a través de la función required se trae la librería que necesita del Liferay AMD Loader.
1.2. Limitaciones
- Configuración compleja
Al usar dos herramientas y usar gradle, hay una configuración compleja e impones un perfil mixto, no es que se deba ser experto, pero un frontend necesitaría algunos conocimientos de backend.
- Desduplicación agresiva.
Con esta primera versión del bundler se definió que todos los portlets de una página que importaban alguna librería, debían importar todos la misma. Por defecto se elegía la librería de mayor versión.
Es decir si tengo 3 portlets en una página y todos usan React, todos importarán el mismo código React de mayor versión.
Esto que en principio era una buena idea en la práctica no fue tanto.
Cómo desarrollador yo podía implementar mi módulo para una versión en concreto de React, y si alguien desplegaba otro módulo con un React superior,mi módulo en tiempo de ejecución apuntaba a esa versión superior sin pasar ningún tipo de prueba.
Esto daba lugar a errores no predecibles.
Por no hablar de las dependencias transitivas, que dejaban de apuntar a sus versiones definidas para apuntar a la versión superior de la librería que estuviera cargada.
En esta versión no se puede configurar ni evitar esa desduplicación.
2. Evolución a Bundler 2.0
2.1. Mejoras en el manejo de dependencias
Estas son las mejoras incluidas para corregir el problema de la desduplicación agresiva.
Bundler 2.0 añade un namespaces a las dependencias de cada módulo, así cada proyecto importa sus propias dependencias.
Pero claro, ahora si tengo tres módulos con la misma librería y los instancio, se cargará tres veces la misma librería.
¿Cómo podemos evitarlo y configurar las dependencias que necesita cáda módulo?
Para esto tenemos los imports.
2.2. Configuracion de imports
- Módulo proveedor
El escenario más típico, es hacerse un módulo proveedor,será en el que declaremos todas las dependencias que vamos a usar en el portal.
Al desplegarse estas librerías se cargarán el Liferay AMD Loader y estaran disponibles para que otros módulos las usen.
- Módulo consumidor
Si queremos que alguno de nuestros módulos usen las librerías que hemos definido en el provider, tendremos que declarar en el fichero .npmbundlerrc la etiqueta import con el módulo y la librería que queremos usar.
De esta forma podemos configurar si queremos que apunte a la librería de otro módulo o queremos que apunte a la librería definida en nuestro módulo .
2.3. Desarrollo 100% javascript
Para conseguir esto se ha sustituido gradle por Yeoman .
El jar resultante, no tiene ninguna clase java.
En el manifest tiene una cabecera que lo que hará es invocar al js portlet extender que processa el jar y genera un portlet al vuelo.
Las características del portlet se pueden definir el package.json . Con anotaciones estándar de portlets.
El JS portlet extender, es un módulo disponible a partir de la 7.1 y que ya viene integrado en la versión 7.2
Al desplegar el jar el servidor Liferay detecta la cabecera y genera un portlet automático con un html vacio que tiene una etiqueta div con un id específico.
Con este id generaremos nuestra interfaz de usuario.
Para pasarnos este id se define en el package.json un javascript index.js que apunta a una función por defecto.
Lo mas importantes.
-
ContextPath: Ruta donde nos bajaremos recursos estático
-
PortltElementId: El identificador del nodo dom dónde nos engancharemos con nuestro framework para manejar nuestra interfaz de usuario.
3. Manos a la obra
Os intentaré resumir las diferentes formas que tenemos hoy por hoy de generar nuestras aplicaciones liferay.
3.1. liferay-npm-bundler
Crearemos un módulo proveedor y un módulo consumidor y el módulo cosumidor apuntará a las dependencias del proveedor.
Vamos a usar nuestro toolkit, para ello en el caso de que no lo tengáis instalado.
npm install -g generator-liferay-js
Tendremos que llamar dos veces a:
yo liferay-js
Una para crear el módulo proveedor y otra para el módulo consumidor.
Una vez creados los módulos, vamos a hacer que nuetro módulo consumidor importe las dependencias de React del módulo proveedor. Para esto:
- Eliminamos la referencia que tenemos package.json
- Configuramos los imports
Cómo vemos sólo hemos tocado el modulo consumidor para que apunte al proveedor. Vamos a desplegar los dos módulos con:
npm run build
npm run deploy
Una vez construidos ambos módulos podemos comprobar que el módulo cosumidor está importando React del proveedor.
Esta forma de generar el módulo permite añadir configuración el el portlet.
3.1. liferay:adapt
Podemos desarrollar nuestra aplicación usando el framework que más nos guste y a través de liferay-js toolkit integrarla en nuestro portal.
Hemos decidido hacer una aplicacón en React usando su propio framework.
npx create-react-app hola-react
cd hola-react
npm start
Dentro de nuestro hola-react
yo liferay-js:adapt
Nuestro toolkit ha convertido esta aplicación en una aplicación desplegable en liferay.
Incluso ha añadido características propias de liferay como la Localización. Para usarla tendremos que llamar a:
Liferay.Language.get('javax.portlet.title.holareact')
Ahora vamos a desplegar nuestra aplicación en el portal.
npm run deploy:liferay
Esta herramienta convierte aplicaciones externas en aplicaciones de Liferay, pero aunque cada vez van añadiendo más funcionalidades, aun tienen ciertas limitaciones, por ejemplo aun no permiten que sean configurables.
4. Conclusión
Cómo vemos, de una forma muy fácil podemos generar nuestros módulos con frameworks javascript y desplegarlos en Liferay.
Ahora sólo me queda aprender React :D
5. Mas Información
Podéis encontrar más información en los links en los que me he basado para redactar este post:
How-to-use-generator-liferay-js
using-javascript-in-your-portlets