Crea una aplicación Angular en minutos con Cypress, StoryBook, Tailwind CSS y Nx
¿Te han pedido que desarrolles una aplicación de ejercicios de codificación para una entrevista? ¿O has querido probar nuevas librerías o características en una aplicación que puedas controlar? ¿O quieres tener una aplicación que puedas mostrar en GitHub?
Bueno, no temas; en este artículo, te mostraré cómo configurar el espacio de trabajo, la aplicación, la biblioteca de interfaz de usuario compartida e incluir Nx, Tailwind CSS, StoryBook y Cypress.
Vale la pena señalar que este es sólo el primero de una serie de artículos en los que profundizaré en la arquitectura, las bibliotecas y las herramientas que harán que el sistema sea fácil de mantener y escalar.
Crea el Workspace
Nx es una potente herramienta para crear y gestionar aplicaciones Angular. Te proporciona un conjunto de herramientas que trabajan juntas para desarrollar, construir y probar aplicaciones Angular. Nx también te proporciona un potente conjunto de herramientas, como análisis estático, integración continua y pruebas automatizadas, que pueden ayudarte a mejorar tus aplicaciones.
Es especialmente útil utilizar Nx en tu aplicación porque te permite mantener tu código coherente, organizado y conforme a las mejores prácticas en varias aplicaciones y bibliotecas desde un único repositorio. Si aún necesitas convencerte, puedes leer este artículo en inglés que detalla cada beneficio de usar Nx en Angular:
Comencemos creando el workspace en Nx con el siguiente comando:
npx create-nx-workspace@latest ng-demos
El CLI te hará una serie de preguntas sobre el workspace, pero lo más importante es que elijas la opción de “Integrated Monorepo”, ya que queremos poder crear múltiples aplicaciones y librerías.
✔ Choose what to create · integrated
✔ What to create in the new workspace · angular-monorepo
✔ Application name · site
✔ Default stylesheet format · scss
✔ Enable distributed caching to make your CI faster · No
Una vez instalado todo, ejecuta la aplicación mediante el comando `nx serve site` y deberías ver algo como esto:
¡Eso es todo para el primer paso! Lo sé, lo sé, era super fácil, pero vamos a profundizar en los siguientes pasos, y espero que esto le muestre lo fácil que es crear un workspace en Nx para un monorepo integrado con una aplicación Angular.
Si estás atascado, asegúrate de revisar el commit aquí:
Añade Tailwind CSS
Tailwind CSS es un framework CSS que facilita la creación de diseños personalizados sin tener que escribir CSS. La biblioteca incluye un conjunto de clases de utilidad que aceleran el proceso de desarrollo y permiten a los desarrolladores centrarse en la creación de diseños personalizados en lugar de escribir CSS.
Existe un plugin para Nx que facilita la instalación de Tailwind y nos deja hacerlo con un único comando que se encarga de todos los ajustes de configuración necesarios:
nx generate @nrwl/angular:setup-tailwind -project=site
El siguiente paso es implementar un theme personalizado, haciendo que la aplicación se vea diferente del resto, y lo haremos personalizando la propiedad `colors` en el archivo de configuración:
//tailwind.config.js
const { createGlobPatternsForDependencies } = require('@nrwl/angular/tailwind');
const colors = require('tailwindcss/colors');
const { join } = require('path');
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
...createGlobPatternsForDependencies(__dirname),
],
theme: {
extend: {
colors: {
primary: {
...colors.indigo,
DEFAULT: colors.indigo[600],
},
accent: {
...colors.slate,
DEFAULT: colors.slate[800],
},
warn: {
...colors.red,
DEFAULT: colors.red[600],
},
'on-warn': {
500: colors.red['50'],
},
},
},
plugins: {},
},
};
Con esto deberíamos estar listos, pero antes de continuar, vamos a añadir dos botones a la app de demo para asegurarnos de que Tailwind está configurado correctamente.
<!--- apps/site/src/app/app.component.html --->
<div class="mt-8 flex gap-x-4 sm:justify-center">
<button
class="inline-block rounded-lg px-4 py-1.5 text-base font-semibold leading-7 text-white shadow-sm bg-primary-600 ring-1 ring-primary hover:bg-primary-700 hover:ring-primary-700"
>
Get started
</button>
<button
class="inline-block rounded-lg px-4 py-1.5 text-base font-semibold leading-7 text-gray-900 bg-accent-200 hover:ring-accent-300 ring-1 ring-gray-900/10 hover:ring-gray-900/20"
>
Live demo
</button>
</div>
Si todo está bien, debería tener los siguientes botones en la página:
🎉 En este paso, has añadido un theme personalizado a tu aplicación y configurado Tailwind.
🤔 Una vez más, si te quedas atascado, puedes ver un commit aquí.
Crea tu librería de componentes compartidos
Uno de los beneficios de tener un mono repo es que puedes tener diferentes librerías y aplicaciones. En este paso, añadiremos una librería de componentes donde podrás añadir todos los componentes que quieras usar en alguna o todas tus aplicaciones.
Para crear la librería, usaremos el siguiente comando que añadirá la librería `common-ui` bajo la carpeta compartida.
nx g @nrwl/angular:library.
--name=ui --prefix=ui --directory=shared
--buildable --simpleName --importPath=@ng-demos/ui
--unitTestRunner=jest --strict --linter=eslint
--addTailwind --skipModule --standalone --style=scss
--viewEncapsulation=Emulated --changeDetection=OnPush
Creo que es importante mencionar lo siguiente sobre algunas de las opciones añadidas:
- addTailwind: Añade Tailwind al proyecto. Necesitamos añadirlo a la librería, para permitir a StoryBook cargar los componentes con los estilos de Tailwind .
- buildable: Tener esta opción nos permitirá generar una librería buildable. En este caso también es necesario ya que usamos la opción “ — addTailwind” y para poder usarla se necesita esta opción o la de “publishable”.
- directory=shared: Esto es para crear el proyecto bajo la carpeta `libs\shared`. Ponerlo en la carpeta “shared” nos permite crear una jerarquía de directorios en la que podemos tener bibliotecas compartidas con todas las apps o sólo con una.
- standalone: Utiliza componentes standalone en lugar de módulos. Por supuesto. ¡Cómo perder la oportunidad de probarlo!
- strict: Crea la librería con una comprobación de tipos más estricta y optimizaciones de compilación.
- prefix=ui: Esto es sólo para usar un pequeño prefijo para los componentes.
Crea tu primer componente
Ahora que tenemos la librería, deberíamos darle una vuelta creando un componente en ella, y esta es la oportunidad perfecta para mover los botones que usan Tailwind que añadimos en el paso anterior.
Ejecuta el siguiente comando para agregar un componente a tu nueva librería de componentes:
nx generate @nrwl/angular:component
--project=shared-ui --name=button --standalone
--viewEncapsulation=Emulated --changeDetection=OnPush
--style=scss --type=component --export
Ahora utiliza el siguiente código para el componente:
// libs/shared/ui/src/lib/button/button.component.ts
import { CommonModule } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
Input,
ViewEncapsulation,
} from '@angular/core';
@Component({
selector: 'ui-button',
standalone: true,
imports: [CommonModule],
templateUrl: './button.component.html',
encapsulation: ViewEncapsulation.Emulated,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ButtonComponent {
@Input() type: 'primary' | 'secondary' = 'primary';
}
<!--- libs/shared/ui/src/lib/button/button.component.html --->
<button
class="inline-block rounded-lg px-4 py-1.5 text-base font-semibold leading-7shadow-sm ring-1"
[ngClass]="{
'text-white bg-primary-600 hover:bg-primary-700 ring-primary hover:ring-primary-700':
type === 'primary',
'text-gray-900 bg-accent-200 hover:ring-accent-300 ring-1 ring-gray-900/10 hover:ring-gray-900/20':
type === 'secondary'
}"
>
<ng-content></ng-content>
</button>
Por último, cambia el código existente en la página para usar el componente que acabas de crear.
<div class="mt-8 flex gap-x-4 sm:justify-center">
<ui-button type="primary">
Get started
</ui-button>
<ui-button type="secondary">
Live demo
</ui-button>
</div>html
🤔 Para no romper la racha, aquí tienes el commit de GitHub por si quieres comparar:
Instala StoryBook y Cypress en tu libreria de componentes
Como esta aplicación debe ser profesional y algo que quieras compartir en tu perfil, vamos a subir un poco el nivel incluyendo un par de librerías en tu biblioteca de componentes que realmente demostrarán tu profesionalidad: StoryBook y Cypress.
StoryBook y Cypress pueden ayudarte a crear aplicaciones Angular profesionales ofreciéndote un potente conjunto de herramientas para crear, probar y escribir componentes.
StoryBook te permite crear componentes de interfaz de usuario de forma rápida y separada del resto de la aplicación. Con un entorno separado, puedes cambiar rápidamente los componentes y probarlos de diferentes maneras. También puedes documentar los componentes con Storybook para que otros miembros del equipo entiendan fácilmente cómo funciona cada componente.
Cypress automatiza las pruebas de interfaz de usuario para realizar pruebas de extremo a extremo desde la perspectiva del usuario y le permite crear conjuntos de pruebas para asegurarse de que su aplicación es estable y funciona bien, aunque siga cambiando.
Para instalar StoryBook, es necesario instalar el plugin Nx:
npm install -D @nrwl/storybook@latest
A continuación, podemos configurar Cypress y StoryBook con un solo comando:
nx generate @nrwl/angular:storybook-configuration
--name=shared-ui --configureCypress
--generateStories --generateCypressSpecs
--linter=eslint --tsConfiguration
🤩 ¿Lo puedes creer? 🤩 ¡¡¡Eso es todo lo que tienes que hacer!!! Tan sencillo, ¿verdad?
Ahora puedes ejecutar `nx run shared-ui-e2e:e2e` y `nx run shared-ui:storybook`
Compartir configuraciones de Tailwind
Como última parte de este tutorial, ya que hemos añadido Tailwind a la librería para permitir que StoryBook cargue los estilos de los componentes, vamos a hacer una refactorización rápida para compartir la configuración de Tailwind y así no tener que configurarlo en cada aplicación y librería y a la vez que StoryBook también use la misma configuración.
Crea un `tailwind-shared.config.js` para tener el theme:
// tailwind-shared.config.js
const colors = require('tailwindcss/colors');
module.exports = {
theme: {
extend: {
colors: {
primary: {
...colors.indigo,
DEFAULT: colors.indigo[600],
},
accent: {
...colors.slate,
DEFAULT: colors.slate[800],
},
warn: {
...colors.red,
DEFAULT: colors.red[600],
},
'on-warn': {
500: colors.red['50'],
},
},
},
plugins: {},
},
};
Modifica los archivos de configuración de Tailwind en la app `apps/site/tailwind.config.js` y la librería `libs/shared/ui/tailwind.config.js` para usar el theme del archivo que acabas de crear.
const { createGlobPatternsForDependencies } = require('@nrwl/angular/tailwind');
const sharedTailwindConfig = require('../../../tailwind-shared.config');
const { join } = require('path');
/** @type {import('tailwindcss').Config} */
module.exports = {
presets: [sharedTailwindConfig],
content: [
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
...createGlobPatternsForDependencies(__dirname),
],
};
Agrega un `tailwind-imports.css` a la carpeta `.storybook`:
/*.storybook/tailwind-imports.css*/
@tailwind base;
@tailwind components;
@tailwind utilities;
Incluye un enlace a este archivo en el “project.json”:
{
"storybook": {
"options": {
…
"styles": [".storybook/tailwind-imports.css"] 👈
},
},
"build-storybook": {
"options": {
…
"styles": ["jo.storybook/tailwind-imports.css"] 👈
},
}
}
Crea una Story
Añade lo siguiente al `button.stories.ts`:
// libs/shared/ui/src/lib/button/button.component.stories.ts
import { Meta, Story } from '@storybook/angular';
import { ButtonComponent } from './button.component';
export default {
title: 'Button',
component: ButtonComponent,
} as Meta<ButtonComponent>;
const Template: Story<ButtonComponent> = (args: ButtonComponent) => {
const { type } = args;
return {
props: args,
template: `<ui-button [type]="type"> Save </ui-button>`,
};
};
export const Primary = Template.bind({});
Primary.args = {
type: 'primary',
};
export const Secondary = Template.bind({});
Secondary.args = {
type: 'secondary',
};
Una vez hecho esto, StoryBook debería tener el siguiente aspecto:
😉 Sí, sí, aquí está el último commit de GitHub para esta guía:
Conclusión
¡Ya todo listo! En este artículo, has aprendido a crear una aplicación profesional utilizando Nx, StoryBook, Cypress, y Tailwind CSS.
Recuerda que esto es sólo el principio; en artículos posteriores, entraré en mayor detalle sobre el uso de StoryBook, Cypress, Linters, e incluso cómo añadir NgRx a tu aplicación.
Así que, sígueme, mantente en sintonía, y espero que esto te haga querer hacer una aplicación que puedas usar como tu sandbox, mostrar herramientas y librerías, o simplemente poner en tu perfil.
¡Únete a nosotros en la ng-conf 2023!
ng-conf | 14–15 de junio de 2023
Talleres | 12–13 de junio de 2023
Lugar | Salt Lake City, UT
ng-conf 2023 es una conferencia de dos días centrada en la construcción de la comunidad Angular. Ven a formar parte de este increíble evento, conoce al equipo de Angular y a las personalidades más importantes de la comunidad. Aprende lo último en Angular, construye tu red y mejora tus habilidades.