El autor del material, cuya traducción publicamos hoy, quiere compartir una historia sobre las tecnologías que utiliza para desarrollar rápidamente prototipos de aplicaciones web. Estas tecnologías incluyen las bibliotecas Fastify y Preact. También usa la biblioteca htm. Se integra fácilmente con Preact y se utiliza para describir elementos DOM utilizando construcciones intuitivas que recuerdan a JSX. Al mismo tiempo, no se necesita un transpilador como Babel para trabajar con él. Después de demostrar las herramientas de desarrollo de prototipos y los métodos para trabajar con él, el autor del material mostrará cómo empaquetar dichas aplicaciones en contenedores Docker. Esto facilita la demostración de aplicaciones a todos los interesados.

Inicio
Hace unas semanas, utilicé el conjunto de tecnologías antes mencionado cuando necesitaba crear una aplicación web prototipo muy simple diseñada para probar, junto con mis colegas, algunas suposiciones.
Mi experimento fue extremadamente exitoso. Pude crear un prototipo muy rápido, los colegas tuvieron la oportunidad de experimentar con él convenientemente, pudieron expresar rápidamente sus impresiones al respecto. Al mismo tiempo, podrían probar el proyecto incluso si Node.js y NPM no estuvieran instalados en sus computadoras.
Todo esto me llevó a la idea de que debería escribir material sobre mi enfoque para la creación rápida de prototipos de aplicaciones web. Es posible que este enfoque sea útil para otra persona. Para aquellos que ya están familiarizados con Fastify y Preact, describiré de inmediato lo más importante, lo que les permitirá poner en práctica mis ideas de inmediato.
Ideas principales
Si ya está familiarizado con Fastify y Preact y desea aprender sobre cómo organizar el desarrollo de proyectos basados en estas tecnologías, entonces está literalmente a un par de pasos de lo que desea. A saber, estamos hablando de los siguientes comandos:
git clone https://github.com/lmammino/fastify-preact-htm-boilerplate.git my-new-project cd my-new-project rm -rf .git npm install
Por supuesto, puede cambiar el nombre del proyecto,
my-new-project
, al nombre de su proyecto.
Después de instalar todo lo que necesita, puede comenzar a trabajar en el proyecto. A saber, estamos hablando de lo siguiente:
- La carpeta
src/ui
contiene archivos de la parte cliente de la aplicación (aquí se utilizan Preact y htm). - La carpeta
src/server
contiene archivos relacionados con el lado del servidor de la aplicación (aquí se usa Fastify).
Al editar los archivos apropiados, puede ejecutar el proyecto:
npm start
Después de eso, puede probarlo yendo a la dirección
localhost:3000
en el navegador.
Y una cosa más. Si te gustó mi desarrollo, estaré inmensamente agradecido por la estrella en
GitHub .
Ahora echemos un vistazo a las tecnologías utilizadas aquí y las características de trabajar con ellas.
Fastify
Fastify es un marco web rápido y económico para Node.js. Este proyecto fue creado originalmente por dos programadores. Ahora, el equipo de quienes trabajan en él tiene 10 personas, más de 130 personas ayudan en el desarrollo del proyecto, recolectó casi 10,000 estrellas en GitHub.
Fastify fue influenciado por los frameworks Node.js como Express y Hapi, que han existido durante bastante tiempo. Originalmente estaba dirigido a la productividad, a la conveniencia de los programadores y a expandir sus capacidades con la ayuda de complementos. Esta, por cierto, es una de mis características favoritas de Fastify.
Si no está familiarizado con el marco de Fastify o desea conocerlo mejor, puedo recomendar su
documentación oficial.
Cabe señalar que estoy relacionado con Fastify. Soy miembro del equipo principal de desarrollo y me dedico principalmente a apoyar el sitio del proyecto y a trabajar en su documentación.
Preact
Preact es una biblioteca para desarrollar interfaces de usuario para proyectos web, que fue creada por una persona como un reemplazo compacto y rápido para React. Este proyecto resultó ser bastante exitoso, ahora todo un equipo de desarrolladores está involucrado en él, en GitHub obtuvo más de 20,000 estrellas.
Una de las razones por las que me gusta Preact es que esta biblioteca tiene una capa extensible para describir los componentes visuales de la aplicación. En circunstancias normales, esta biblioteca se puede usar usando JSX en combinación con Babel para traducir el código, pero si no desea instalar Babel y configurar el proceso de compilación de la aplicación, puede usar Preact, por ejemplo, junto con la biblioteca
htm , que usa plantillas literales y no requiere transpilación al iniciar proyectos en los que se utiliza en navegadores modernos.
En este artículo usaremos la biblioteca htm y pronto consideraremos algunos ejemplos.
Resumen del proyecto
Aquí nos fijamos en todo el proceso de creación de un proyecto. Nuestro objetivo será desarrollar una aplicación web simple que muestre información sobre la hora en el servidor en el momento de su lanzamiento. Aquí, para que quede más claro por qué nos esforzaremos.
Aplicación en navegadorEsta es una aplicación de página única (SPA), en la que Preact y htm se usan para formar su parte cliente, y Fastify se usa para crear una API diseñada para recibir el tiempo del servidor.
Un lector atento puede notar que la página que se muestra en la figura anterior tiene un ícono de favicon. Es cierto, él es muy pequeño allí, así que voy a facilitar la tarea a aquellos que, rompiendo los ojos, están tratando de distinguir. Aquí hay una versión ampliada de la misma.
FaviconConfigurar el lado del servidor de la aplicación
Comencemos creando una nueva carpeta:
mkdir server-time cd server-time
Ahora inicialice el proyecto NPM e instale Fastify:
npm init -y npm i --save fastify@next fastify-static@next fastify-cli
Tenga en cuenta que usé la construcción
@next
al describir algunos
@next
dependencia. Esto se hace para que el proyecto use la biblioteca Fastify 2, que actualmente se encuentra en un estado candidato de lanzamiento, pero muy pronto se convertirá en la versión estable principal.
Tenga en cuenta que también puede crear un nuevo proyecto basado en Fastify utilizando la
fastify-cli
línea de comandos
fastify-cli
:
npx fastify-cli generate server-time
Al momento de escribir este material, este equipo crea un proyecto diseñado para usar Fastify 1.x, pero muy pronto, después del lanzamiento de Fastify 2, esta herramienta se actualizará.
Analicemos los paquetes instalados:
fastify
es un componente central del marco.fastify-static
es un complemento adicional que le permite servir convenientemente archivos estáticos con el servidor Fastify.fastify-cli
es una herramienta de línea de comandos que le permite crear proyectos basados en Fastify.
Por el momento, estamos listos para crear una API basada en Fastify. Pongamos el código del servidor en el
src/server/server.js
:
const path = require('path') module.exports = async function(fastify, opts) { // `src/ui` fastify.register(require('fastify-static'), { root: path.join(__dirname, '..', 'ui'), }) // API fastify.get('/api/time', async (request, reply) => { return { time: new Date().toISOString() } }) }
Creo que el código anterior se explica bien, pero hay algunos detalles interesantes de los que vale la pena hablar. Esto será especialmente útil para aquellos que no tienen experiencia con Fastify.
Lo primero a lo que puede prestar atención en este código es que aquí se usa la palabra clave
async
. Fastify admite el desarrollo de estilo asíncrono / en espera y un enfoque de devolución de llamada más tradicional. Qué elegir exactamente depende de las preferencias de un desarrollador en particular.
Otro detalle interesante es que definimos el servidor aquí como un módulo exportado. Este módulo (esto se llama un "complemento" en la jerga de Fastify) es una función que toma una instancia de Fastify (
fastify
) y un conjunto de opciones (
opts
) como argumentos. Dentro de la declaración del módulo, podemos usar una instancia de
fastify
para registrar complementos. Esto es exactamente lo que sucede con el
fastify-static
. También podemos describir puntos finales HTTP utilizando métodos especiales como
fastify.get
y
fastify.post
.
El enfoque modular utilizado aquí, aunque parece un poco inusual, tiene sus ventajas. Para empezar, debe tenerse en cuenta que le permite combinar varios servidores. Imagine que ha creado un servidor diseñado para servir un blog y otro para un foro. Se pueden integrar fácilmente en una aplicación existente uniéndolos a rutas como
/blog
y
/forum
.
Además, este enfoque le permite abstraer aplicaciones y sub-aplicaciones de los enlaces del servidor (por ejemplo, enlace de socket), pasando la solución a esta tarea ya sea a la aplicación raíz o
fastify-cli
.
Inicie el servidor utilizando la
fastify
línea de comandos
fastify
:
node_modules/.bin/fastify start --log-level info src/server/server.js
Para simplificar nuestra vida, podemos agregar este comando a la sección de
scripts
de nuestro archivo
package.json
:
{ "scripts": { "start": "fastify start --log-level info src/server/server.js" } }
Antes de iniciar realmente el servidor, debemos asegurarnos de que haya una carpeta en la que se ubicarán los recursos estáticos. De lo contrario,
fastify-static
error. Crea esta carpeta:
mkdir src/ui
Ahora podemos iniciar la aplicación con el comando
npm start
y navegar usando el navegador a
localhost:3000/api/time
.
Si todo funciona correctamente, en el navegador puede ver algo como lo siguiente:
{ "time": "2019-02-17T19:32:03.354Z" }
En este punto, puede apreciar otra buena característica de Fastify. Se basa en el hecho de que la serialización JSON, en el caso de que una ruta determinada devuelva un objeto, se aplica automáticamente.
Ahora se completa el trabajo en la API del servidor. Tengamos una interfaz.
Configuración frontend
Todo el código de nuestro proyecto relacionado con la interfaz se ubicará en la carpeta
src/ui
. Constará de 5 archivos:
app.js
: crea el código de la aplicación.bootstrap.min.css
: código CSS para diseñar la aplicación (se toma directamente del marco Bootstrap).favicon.ico
: archivo favicon. Si está desarrollando una aplicación seria, no puede prescindir de un buen archivo favicon.index.html
es el archivo HTML principal de nuestra aplicación de una página.preacthtm.js
: código de las bibliotecas Preact y htm.
Primero, coloque los archivos en la carpeta, que son estilos, bibliotecas y el ícono de favicon:
curl "https://unpkg.com/htm@2.0.0/preact/standalone.js" > src/ui/preacthtm.js curl "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" > src/ui/bootstrap.min.css curl "https://github.com/lmammino/fastify-preact-htm-boilerplate/blob/master/src/ui/favicon.ico?raw=true" > src/ui/favicon.ico
Ahora cree el archivo
src/ui/index.html
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <!-- Bootstrap CSS --> <link rel="stylesheet" href="/bootstrap.min.css" /> <title>My awesome server time</title> </head> <body> <div id="app"></div> <!-- JavaScript --> <script src="/preacthtm.js"></script> <script src="/app.js"></script> </body> </html>
Tenemos ante nosotros una página HTML muy ordinaria con la que cargamos todos los recursos (CSS y JS) y creamos un elemento
<div>
vacío con la
app
identificación, en el que enviaremos nuestra aplicación durante la ejecución del proyecto.
Ahora eche un vistazo al código de la aplicación, que debe estar en el
src/ui/app.js
:
/* htmPreact */ const { html, Component, render } = htmPreact class App extends Component { componentDidMount() { this.setState({ loading: true, time: null }) fetch('/api/time') .then(response => response.json()) .then(data => this.setState({ loading: false, time: data.time })) } render(props, state) { return html` <div class="container mt-5"> <div class="row justify-content-center"> <div class="col"> <h1>Hello from your new App</h1> <div> ${state.loading && html` <p>Loading time from server...</p> `} ${state.time && html` <p>Time from server: <i><font color="#999999">${state.time}</font></i> </p> `} </div> <hr /> <div> Have fun changing the code from this boilerplate: <ul> <li>UI code available at <code>/src/ui</code></li> <li>Server-side code available at <code>/src/server</code></li> </ul> </div> </div> </div> </div> ` } } render( html` <${App} /> `, document.getElementById('app') )
Solo hay un componente con estado en esta aplicación llamado
App
. El estado de este componente incluye 2 variables:
loading
es una variable lógica que se usa para indicar si se está realizando una solicitud a la API del servidor en un determinado momento para obtener información sobre la hora del servidor.time
: una cadena que contiene la última información de tiempo recibida del servidor.
Si está familiarizado con React, puede comprender fácilmente el código anterior.
Usando Preact y htm, podemos crear componentes declarando clases que extienden la clase de
Component
incorporada.
En esta clase, podemos describir el comportamiento de un componente usando métodos de ciclo de vida como
componentDidMount()
, y también usar un método que se comporta como un método
render()
regular de React.
En nuestro caso, tan pronto como el componente se adjunte a la página (método
componentDidMount()
), establecemos la propiedad de
loading
estado y ejecutamos una solicitud de API usando
fetch
.
Una vez completada la solicitud, establecemos el valor de la propiedad de estado de
time
y restablecemos la propiedad de
loading
a
false
.
El método
render()
se llama automáticamente cada vez que cambia el estado de un componente o cuando se le pasan nuevas propiedades. En este método, describimos el componente DOM usando htm.
La biblioteca htm le permite describir los nodos DOM utilizando literales de plantillas etiquetadas con una etiqueta especial:
html
. Dentro de nuestra plantilla literal, las expresiones dinámicas pueden estar presentes, como las que usamos para verificar el estado y decidir qué mostrar si la aplicación está cargando datos del servidor y si los datos ya están cargado
También vale la pena señalar que necesitamos crear una instancia de la aplicación y mostrarla en una página HTML. Esto se hace utilizando la función
render()
del objeto global
htmPreact
.
Ahora se ha completado el trabajo en la aplicación front-end. Puede reiniciar el servidor, vaya a
localhost:3000
y experimente con lo que acabamos de crear. Por ejemplo, puede desarrollar el suyo en base a esta aplicación. Y cuando lo que cree parezca lo suficientemente interesante como para mostrárselo a otra persona, probablemente le sea útil empacar su aplicación en un contenedor Docker.
Aplicación en contenedores
Creo que la mejor manera de mostrar a otros sus nuevos proyectos pequeños es utilizar las capacidades de Docker para este propósito.
Gracias a Docker, cualquier persona que intente ejecutar su aplicación en casa no tendrá que pensar si tiene instalada la versión adecuada de Node.js y NPM, no necesitará descargar el código fuente de la aplicación para asegurarse de que ingrese la secuencia correcta de comandos , instale sus dependencias e inicie el servidor.
Para empacar la aplicación en el contenedor Docker, necesitamos crear un
Dockerfile
muy simple en la carpeta raíz de nuestro proyecto:
FROM node:11-alpine WORKDIR /app COPY . /app RUN npm install --production EXPOSE 3000 CMD ["npm", "start"]
Aquí describimos las siguientes acciones:
- La imagen se crea en base a la imagen Node.js 11, construida sobre la base de Alpine Linux.
- Todo lo de la carpeta actual se copia en la carpeta
/app
del contenedor. - Después de eso, ejecutamos el comando
npm install
para descargar e instalar las dependencias. El uso del indicador --production
lleva al hecho de que solo se instalarán las dependencias necesarias para la implementación del proyecto en producción. Esto acelera la creación de imágenes si el proyecto usa muchas dependencias de desarrollo. - Indicamos que el contenedor debe tener poro abierto 3000, en el cual, por defecto, el servidor funcionará.
- Al final, describimos un comando,
npm start
, que se ejecutará cuando se inicie el contenedor. Ella lanza la aplicación.
Para recopilar la imagen para el contenedor, ejecute el siguiente comando:
docker build -t server-time .
Después de unos segundos, la imagen debería estar lista y debería poder iniciar el contenedor:
docker run -it -p 3000:3000 server-time
La
-p
permite configurar la conexión entre el puerto de contenedor 3000 y el puerto local 3000. Esto le permitirá acceder a la aplicación en contenedor en
localhost:3000
.
Ahora está listo para compartir su aplicación con otras personas. Para ejecutarlo en el entorno Docker, es suficiente, siempre que Docker esté instalado en la computadora, para ejecutar los dos comandos anteriores en su carpeta.
Resumen
En este artículo, hablamos sobre cómo crear un entorno para el rápido desarrollo de aplicaciones web usando Fastify y Preact. Además, hablamos sobre cómo compartir la aplicación con otras personas que usan Docker.
Como se mencionó anteriormente, las herramientas propuestas están diseñadas para la creación rápida de prototipos, por lo que ahora puede que se pregunte qué falta aquí para desarrollar aplicaciones reales. Lo más probable es que cuando habla de "aplicaciones reales", se refiera a las siguientes características:
- Compilación de recursos de la parte front-end de la aplicación: creación de archivos optimizados (paquetes), posiblemente utilizando Webpack, Babel u otras herramientas.
- Enrutamiento en el front-end de la aplicación.
- Representación del servidor
- Medios de almacenamiento permanente de datos.
Todavía no se han agregado todas estas posibilidades para desarrollar aplicaciones reales al conjunto de tecnologías discutidas aquí, por lo que por ahora lo percibo como una herramienta para desarrollar prototipos. Estoy seguro de que si te gustó lo que viste y consideras todo esto como la base para futuras aplicaciones que resuelven problemas reales, puedes encontrar fácilmente lo que necesitas y crear aplicaciones listas para Fastify y Preact lanzamiento de producción.
Estimados lectores! ¿Cómo se prototipan las aplicaciones web?
