Utilizar require() en aplicaciones con Angular y Electron

Ignacio Buioli
- 02/06/2017

Hay ocasiones en que nuestros desarrollos necesitan estar envueltos en una plataforma cómoda para permitirnos una producción más eficiente. Hace poco tiempo comentábamos como integrar una app de Angular en un entorno de Electron, pero no siempre la integración se limita tan solo a la eficiencia de recursos. Por ejemplo, supongamos que queremos desarrollar una WebApp de la cual pretendemos compilar en una App de escritorio que guarde una imagen generada por el usuario. Necesitaremos trabajar con los paquetes de Node que trabajan con el servidor (en este caso con FS). Muy emocionados pondremos el require("fs") en nuestra App de Angular y ejecutaremos npm start solo para darnos cuenta, casi al instante, que Angular nos avisará sobre un error. Desde una App de Electron no existe este problema, puesto que trabaja directamente con un servidor local. En este punto tenemos dos opciones: resignarnos a utilizar Angular si vamos a trabajar con paquetes de Node, o buscar una integración. Desde luego, nuestra meta siempre es el camino de la integración.

No es posible cargar esa clase de paquetes de Node en una App de Angular si esta va a trabajar por su cuenta, pero con el soporte de Electron las cosas cambian (siempre y cuando usemos Electron como versión final, Angular servirá para testeos rápidos que no requieran de los paquetes de Node). El truco consiste en aprovechar el sistema de renderizado de Angular. Cuando utilizamos la etiqueta por defecto <app-root> todo aquello que esté incluido posteriormente será eliminado y remplazado con el contenido renderizado por los scripts, esto significa que podemos cargar scripts antes de dicho bloque de código. Si queremos, entonces, requerir la librería FS de Node vamos a incluir el siguiente bloque en el index.html de la WebApp, antes del <app-root>:

 

<script type="text/javascript">
    var fs = undefined;
    if (window["require"]) {
       fs = require("fs");
    }
</script>

 

Este bloque de código evalúa si existe la posibilidad de utilizar require(), y en caso positivo la utiliza. Luego, para utilizarlo en un service de Angular, tenemos que cargarlo luego de los imports de la siguiente manera:

 

export const fs : any = window["fs"];

 

De esta forma cuando llamemos a la variable fs tendremos acceso a todas las funciones integradas en el paquete FS.