Sitio Web React
Este generador crea un nuevo sitio web React con shadcn/ui configurado por defecto, junto con la infraestructura AWS CDK o Terraform para desplegar tu sitio web en la nube como un sitio web estático alojado en S3, servido por CloudFront y protegido por WAF.
La aplicación generada utiliza Vite como herramienta de construcción y empaquetador. Utiliza TanStack Router para enrutamiento con seguridad de tipos.
Generar un Sitio Web React
Sección titulada «Generar un Sitio Web React»Puedes generar un nuevo Sitio Web React de dos maneras:
pnpm nx g @aws/nx-plugin:ts#website --framework=reactyarn nx g @aws/nx-plugin:ts#website --framework=reactnpx nx g @aws/nx-plugin:ts#website --framework=reactbunx nx g @aws/nx-plugin:ts#website --framework=reactTambién puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:ts#website --framework=react --dry-runyarn nx g @aws/nx-plugin:ts#website --framework=react --dry-runnpx nx g @aws/nx-plugin:ts#website --framework=react --dry-runbunx nx g @aws/nx-plugin:ts#website --framework=react --dry-run- Instale el Nx Console VSCode Plugin si aún no lo ha hecho
- Abra la consola Nx en VSCode
- Haga clic en
Generate (UI)en la sección "Common Nx Commands" - Busque
@aws/nx-plugin - ts#website - Complete los parámetros requeridos
- framework: react
- Haga clic en
Generate
Opciones
Sección titulada «Opciones»| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
| name Requerido | string | - | El nombre de la aplicación. |
| framework | react | react | El framework frontend a utilizar. |
| directory | string | packages | El directorio de la nueva aplicación. |
| subDirectory | string | - | El subdirectorio en el que se coloca el proyecto. Por defecto, este es el nombre del proyecto. |
| ux | none | cloudscape | shadcn | shadcn | El proveedor de UX preferido. |
| tailwind | boolean | true | Habilitar TailwindCSS para estilos basados en utilidades. |
| tanstackRouter | boolean | true | Habilitar Tanstack router para enrutamiento con seguridad de tipos. |
| infra | cloudfront-s3 | none | cloudfront-s3 | El tipo de infraestructura con la que desplegar tu sitio web. |
| iac | inherit | cdk | terraform | inherit | El proveedor de IaC preferido. Por defecto, se hereda de tu selección inicial. |
| preferInstallDependencies | boolean | true | Si se prefiere instalar las dependencias después de que se ejecute el generador. Establece en false para diferir la instalación cuando se ejecutan múltiples generadores en lote (la instalación aún se ejecuta si es necesario para que los generadores subsecuentes puedan calcular el grafo de proyectos de Nx); instala una vez al final. |
Salida del Generador
Sección titulada «Salida del Generador»El generador creará la siguiente estructura de proyecto en el directorio <directory>/<name>:
- index.html HTML entry point
- public Static assets
Directoriosrc
- main.tsx Application entry point with React setup
- config.ts Application configuration (eg. logo)
Directoriocomponents
- AppLayout Components for the overall layout and navigation bar
Directoriohooks
- useAppLayout.tsx Hook for adjusting the AppLayout from nested components (Cloudscape only)
Directorioroutes
- index.tsx Example route (or page) for TanStack Router
- styles.css Global styles
- vite.config.mts Vite and Vitest configuration
- tsconfig.json Base TypeScript configuration for source and tests
- tsconfig.app.json TypeScript configuration for source code
- tsconfig.spec.json TypeScript configuration for tests
- package.json Project manifest defining the project’s package name and dependencies
Infraestructura
Sección titulada «Infraestructura»Dado que este generador proporciona infraestructura como código basada en tu iac elegido, creará un proyecto en packages/common que incluye las construcciones CDK o módulos Terraform relevantes.
El proyecto común de infraestructura como código está estructurado de la siguiente manera:
Directoriopackages/common/constructs
Directoriosrc
Directorioapp/ Constructs for infrastructure specific to a project/generator
- …
Directoriocore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Directoriopackages/common/terraform
Directoriosrc
Directorioapp/ Terraform modules for infrastructure specific to a project/generator
- …
Directoriocore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
El generador crea infraestructura como código para desplegar tu sitio web basándose en tu iac seleccionado:
Directoriopackages/common/constructs/src
Directorioapp
Directoriostatic-websites
- <name>.ts Infrastructure specific to your website
Directoriocore
- static-website.ts Generic StaticWebsite construct
Directoriopackages/common/terraform/src
Directorioapp
Directoriostatic-websites
Directorio<name>
- <name>.tf Module specific to your website
Directoriocore
Directoriostatic-website
- static-website.tf Generic static website module
Arquitectura
Sección titulada «Arquitectura»El sitio web desplegado tiene la siguiente arquitectura:
Implementar tu Sitio Web
Sección titulada «Implementar tu Sitio Web»La documentación de React es un buen lugar para comenzar a aprender los conceptos básicos de construcción con React.
Puedes consultar la documentación de Cloudscape para obtener detalles sobre los componentes disponibles y cómo usarlos.
Puedes consultar la documentación de shadcn/ui para obtener detalles sobre los componentes disponibles y cómo usarlos.
Crear una Ruta/Página
Sección titulada «Crear una Ruta/Página»Tu sitio web viene con TanStack Router configurado por defecto. Esto facilita agregar nuevas rutas:
- Ejecutar el Servidor de Desarrollo Local
- Crea un nuevo archivo
<page-name>.tsxensrc/routes, con su posición en el árbol de archivos representando la ruta - Observa que un
RouteyRouteComponentse generan automáticamente para ti. ¡Puedes comenzar a construir tu página aquí!
Navegar Entre Páginas
Sección titulada «Navegar Entre Páginas»Puedes usar el componente Link o el hook useNavigate para navegar entre páginas:
import { Link, useNavigate } from '@tanstack/react-router';
export const MyComponent = () => { const navigate = useNavigate();
const submit = async () => { const id = await ... // Use `navigate` for redirecting after some asynchronous action navigate({ to: '/products/$id', { params: { id }} }); };
return ( <> <Link to="/products">Cancel</Link> <Button onClick={submit}>Submit</Button> </> )};Para más detalles, consulta la documentación de TanStack Router.
Desplegar tu Sitio Web
Sección titulada «Desplegar tu Sitio Web»El generador de sitios web React crea infraestructura como código CDK o Terraform basándose en tu iac seleccionado. Puedes usar esto para desplegar tu sitio web.
Para desplegar tu sitio web, recomendamos usar el generador ts#infra para crear una aplicación CDK.
Puedes usar el constructo CDK generado para ti en packages/common/constructs para desplegar tu sitio web.
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
new MyWebsite(this, 'MyWebsite'); }}Esto configura:
- Un bucket S3 para alojar los archivos de tu sitio web estático
- Distribución CloudFront para entrega de contenido global
- Web ACL de WAF para protección de seguridad
- Control de Acceso de Origen para acceso seguro a S3
- Despliegue automático de archivos del sitio web y configuración en tiempo de ejecución
Para desplegar tu sitio web, recomendamos usar el generador terraform#project para crear un proyecto Terraform.
Puedes usar el módulo Terraform generado para ti en packages/common/terraform para desplegar tu sitio web.
# Deploy websitemodule "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 }}Esto configura:
- Un bucket S3 para alojar los archivos de tu sitio web estático
- Distribución CloudFront para entrega de contenido global
- Web ACL de WAF para protección de seguridad (desplegado en us-east-1)
- Control de Acceso de Origen para acceso seguro a S3
- Despliegue automático de archivos del sitio web y configuración en tiempo de ejecución
Encabezados de Seguridad
Sección titulada «Encabezados de Seguridad»La distribución CloudFront aplica una política de encabezados de respuesta que establece Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options: DENY, Referrer-Policy y una Content-Security-Policy en todas las respuestas.
Se aplica una Content-Security-Policy predeterminada. Restringe scripts y framing para mitigar XSS y clickjacking, mientras permite conexiones HTTPS y WSS para que el sitio web pueda llamar a endpoints de servicios AWS (como API Gateway, Cognito y Bedrock AgentCore) cuyas URLs solo se conocen en tiempo de despliegue. Para ajustar la política (por ejemplo, para restringir connect-src a tus orígenes específicos), edita el valor content_security_policy en tu static-website.ts (CDK) o static-website.tf (Terraform) generado.
runtime-config.json se sirve con Cache-Control: no-cache para que los navegadores siempre obtengan la configuración más reciente después de un redespliegue, en lugar de usar una copia en caché obsoleta.
La distribución CloudFront está protegida por un Web ACL de AWS WAFv2 por defecto. El Web ACL utiliza el conjunto de reglas predeterminado administrado por AWS (AWSManagedRulesCommonRuleSet y AWSManagedRulesKnownBadInputsRuleSet), proporcionando protección contra exploits web comunes incluyendo el OWASP Top 10.
Para optar por no usarlo, establece enableWaf en false cuando crees tu sitio web:
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyWebsite, suppressRules } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
const website = new MyWebsite(this, 'MyWebsite', { enableWaf: false, });
// Disabling WAF fails the checkov CKV_AWS_68 check ("CloudFront // Distribution should have WAF enabled"). Suppress it explicitly. suppressRules( website.cloudFrontDistribution, ['CKV_AWS_68'], 'WAF is intentionally disabled for this distribution', ); }}Para optar por no usarlo, establece enable_waf en false:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } enable_waf = false}Cifrado de Bucket
Sección titulada «Cifrado de Bucket»El bucket del sitio web, el bucket de logs de la distribución CloudFront y el grupo CloudWatch Logs que recibe sus logs de acceso al servidor están cifrados con una clave AWS KMS administrada por el cliente por defecto. Esta clave se crea automáticamente para ti, con rotación de clave habilitada.
Si deseas usar una configuración de cifrado diferente, pasa las propiedades encryption, encryptionKey y enableKeyRotation cuando crees tu sitio web:
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { BucketEncryption } from 'aws-cdk-lib/aws-s3';import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
new MyWebsite(this, 'MyWebsite', { encryption: BucketEncryption.S3_MANAGED, }); }}Para usar tu propia clave KMS en lugar de una creada automáticamente, pasa encryptionKey:
new MyWebsite(this, 'MyWebsite', { encryptionKey: myKey,});enableKeyRotation (predeterminado true) solo se aplica a la clave creada automáticamente, es decir, cuando encryption es BucketEncryption.KMS (el predeterminado) y no se proporciona encryptionKey:
new MyWebsite(this, 'MyWebsite', { enableKeyRotation: false,});Si deseas usar una configuración de cifrado diferente, establece las variables encryption, kms_key_arn, create_kms_key y enable_key_rotation:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } encryption = "S3_MANAGED"}Para usar tu propia clave KMS en lugar de una creada automáticamente, pasa kms_key_arn y establece create_kms_key en false:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } kms_key_arn = aws_kms_key.website.arn create_kms_key = false}Una clave proporcionada por el cliente ya debe otorgar a los principales de servicio CloudWatch Logs, S3 y CloudFront los permisos que necesitan en su propia política de clave.
enable_key_rotation (predeterminado true) solo se aplica a la clave creada automáticamente, es decir, cuando encryption es "KMS" (el predeterminado) y create_kms_key es true:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } enable_key_rotation = false}Dominio Personalizado y TLS
Sección titulada «Dominio Personalizado y TLS»Por defecto, la distribución usa el nombre de dominio CloudFront predeterminado (*.cloudfront.net) y su certificado predeterminado, que no admite la aplicación de una versión TLS mínima de 1.2. Para servir tu sitio web desde tu propio dominio, proporciona un certificado ACM (que debe residir en us-east-1 para su uso con CloudFront) y tus nombres de dominio. Entonces se aplica una versión TLS mínima de 1.2 para los espectadores:
Pasa las propiedades certificate y domainNames cuando crees tu sitio web:
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { Certificate } from 'aws-cdk-lib/aws-certificatemanager';import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
new MyWebsite(this, 'MyWebsite', { domainNames: ['www.example.com'], certificate: Certificate.fromCertificateArn(this, 'Cert', 'arn:aws:acm:us-east-1:123456789012:certificate/...'), }); }}Establece las variables custom_domain_names y acm_certificate_arn:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } custom_domain_names = ["www.example.com"] acm_certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/..."}También necesitarás crear registros DNS (por ejemplo en Route 53) apuntando tu dominio a la distribución CloudFront.
Configuración en Tiempo de Ejecución
Sección titulada «Configuración en Tiempo de Ejecución»La configuración de tu infraestructura se proporciona a tu sitio web a través de Configuración en Tiempo de Ejecución. Esto permite que tu sitio web acceda a detalles como URLs de API que no se conocen hasta que tu aplicación está desplegada.
Infraestructura
Sección titulada «Infraestructura»El constructo CDK RuntimeConfig se puede usar para agregar y recuperar configuración en tu infraestructura CDK. Los constructos CDK generados por los generadores de @aws/nx-plugin (como ts#api y py#api) agregarán automáticamente valores apropiados al RuntimeConfig.
Tu constructo CDK de sitio web desplegará el namespace connection de la configuración en tiempo de ejecución como un archivo runtime-config.json en la raíz de tu bucket S3.
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyWebsite, MyApi } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
// Website can be declared at any point, since runtime config is resolved lazily new MyWebsite(this, 'MyWebsite');
// Automatically adds values to the RuntimeConfig new MyApi(this, 'MyApi', { integrations: MyApi.defaultIntegrations(this).build(), }); }}Con Terraform, la configuración en tiempo de ejecución se gestiona a través de los módulos runtime-config. Los módulos Terraform generados por los generadores de @aws/nx-plugin (como ts#api y py#api) agregarán automáticamente valores apropiados a la configuración en tiempo de ejecución.
Tu módulo Terraform de sitio web desplegará el namespace connection de la configuración en tiempo de ejecución como un archivo runtime-config.json en la raíz de tu bucket S3.
module "asset_bucket" { source = "../../common/terraform/src/core/asset-bucket"}
# Automatically adds values to runtime configmodule "my_api" { source = "../../common/terraform/src/app/apis/my-api"
asset_bucket_name = module.asset_bucket.bucket_name}
# Automatically deploys the runtime config to runtime-config.jsonmodule "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 }
# Ensure API is deployed first to add to runtime config depends_on = [module.my_api]}Código del Sitio Web
Sección titulada «Código del Sitio Web»En tu sitio web, puedes usar el hook useRuntimeConfig para recuperar valores de la configuración en tiempo de ejecución:
import { useRuntimeConfig } from '../hooks/useRuntimeConfig';
const MyComponent = () => { const runtimeConfig = useRuntimeConfig();
// Access values in the runtime config here const apiUrl = runtimeConfig.apis.MyApi;};Configuración en Tiempo de Ejecución Local
Sección titulada «Configuración en Tiempo de Ejecución Local»Al ejecutar el servidor de desarrollo local, necesitarás un archivo runtime-config.json en tu directorio public para que tu sitio web local conozca las URLs del backend, configuración de identidad, etc.
Tu proyecto de sitio web está configurado con un objetivo load-runtime-config que puedes usar para descargar el archivo runtime-config.json de una aplicación desplegada:
pnpm nx load-runtime-config <my-website>yarn nx load-runtime-config <my-website>npx nx load-runtime-config <my-website>bunx nx load-runtime-config <my-website>Servidor de Desarrollo Local
Sección titulada «Servidor de Desarrollo Local»El comando canónico para desarrollo local es dev, que inicia tu sitio web (y cualquier servidor local para APIs que hayas conectado) con un solo comando:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>El objetivo serve también está disponible para cuando necesites controlar cuánto de tu aplicación se ejecuta localmente versus apuntando a infraestructura AWS desplegada. Para una descripción general más amplia del desarrollo local en proyectos conectados, incluyendo cómo se comporta dev para proyectos con múltiples componentes, consulta la guía de Desarrollo Local.
Objetivo Serve
Sección titulada «Objetivo Serve»El objetivo serve inicia un servidor de desarrollo local para tu sitio web. Este objetivo requiere que hayas desplegado cualquier infraestructura de soporte con la que el sitio web interactúe, y que hayas cargado la configuración en tiempo de ejecución local.
Puedes ejecutar este objetivo con el siguiente comando:
pnpm nx serve <my-website>yarn nx serve <my-website>npx nx serve <my-website>bunx nx serve <my-website>Este objetivo es útil para trabajar en cambios del sitio web mientras apuntas a APIs “reales” desplegadas y otra infraestructura.
Objetivo Dev
Sección titulada «Objetivo Dev»El objetivo dev inicia un servidor de desarrollo local para tu sitio web (con Vite MODE establecido en local-dev), así como iniciando cualquier servidor local para APIs que hayas conectado a tu sitio web a través del Generador de Conexión.
Cuando tu servidor de sitio web local se ejecuta a través de este objetivo, runtime-config.json se sobrescribe automáticamente para apuntar a las URLs de tu API ejecutándose localmente.
Puedes ejecutar este objetivo con el siguiente comando:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>Este objetivo es útil cuando estás trabajando en tu sitio web y API y deseas iterar rápidamente sin desplegar tu infraestructura.
Autenticación Simulada
Cuando se ejecuta en este modo y no hay runtime-config.json presente, si has configurado Autenticación Cognito (a través del generador ts#website#auth), el inicio de sesión se omitirá y las solicitudes a tus servidores locales no incluirán encabezados de autenticación.
Para habilitar el inicio de sesión y la autenticación para dev, despliega tu infraestructura y carga la configuración en tiempo de ejecución.
Construcción
Sección titulada «Construcción»Puedes construir tu sitio web usando el objetivo build. Esto ejecuta los objetivos bundle, compile, test y lint, verificando tipos, empaquetando, probando y lintando tu sitio web.
pnpm nx build <my-website>yarn nx build <my-website>npx nx build <my-website>bunx nx build <my-website>El objetivo bundle usa Vite para crear un paquete de producción en el directorio raíz dist/packages/<my-website>/bundle. Este es el artefacto desplegable consumido por tu infraestructura de sitio web. Puedes ejecutarlo por sí solo:
pnpm nx bundle <my-website>yarn nx bundle <my-website>npx nx bundle <my-website>bunx nx bundle <my-website>Pruebas
Sección titulada «Pruebas»Probar tu sitio web es muy similar a escribir pruebas en un proyecto TypeScript estándar, así que consulta la guía de proyecto TypeScript para más detalles.
Para pruebas específicas de React, React Testing Library ya está instalado y disponible para que lo uses para escribir pruebas. Para más detalles sobre su uso, consulta la documentación de React Testing Library.
Puedes ejecutar tus pruebas usando el objetivo test:
pnpm nx test <my-website>yarn nx test <my-website>npx nx test <my-website>bunx nx test <my-website>Conexiones
Sección titulada «Conexiones»Usa el generador connection para integrar este proyecto con otros en tu workspace. Las siguientes conexiones involucran este proyecto:
