React Website
Este gerador cria um novo site React com shadcn/ui configurado por padrão, juntamente com a infraestrutura AWS CDK ou Terraform para implantar seu site na nuvem como um site estático hospedado no S3, servido pelo CloudFront e protegido pelo WAF.
A aplicação gerada usa Vite como ferramenta de build e bundler. Ela usa TanStack Router para roteamento type-safe.
Gerar um React Website
Seção intitulada “Gerar um React Website”Você pode gerar um novo React Website de duas maneiras:
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=reactVocê também pode realizar uma execução simulada para ver quais arquivos seriam alterados
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 o Nx Console VSCode Plugin se ainda não o fez
- Abra o console Nx no VSCode
- Clique em
Generate (UI)na seção "Common Nx Commands" - Procure por
@aws/nx-plugin - ts#website - Preencha os parâmetros obrigatórios
- framework: react
- Clique em
Generate
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
| name Obrigatório | string | - | O nome da aplicação. |
| framework | react | react | O framework frontend a ser usado. |
| directory | string | packages | O diretório da nova aplicação. |
| subDirectory | string | - | O subdiretório onde o projeto é colocado. Por padrão, este é o nome do projeto. |
| ux | none | cloudscape | shadcn | shadcn | O provedor de UX preferido. |
| tailwind | boolean | true | Ativar TailwindCSS para estilização utility-first. |
| tanstackRouter | boolean | true | Ativar roteador Tanstack para roteamento type-safe. |
| infra | cloudfront-s3 | none | cloudfront-s3 | O tipo de infraestrutura para implantar seu website. |
| iac | inherit | cdk | terraform | inherit | O provedor de IaC preferido. Por padrão, este é herdado da sua seleção inicial. |
| preferInstallDependencies | boolean | true | Se deve preferir instalar dependências após a execução do gerador. Defina como false para adiar a instalação ao executar múltiplos geradores em lote (uma instalação ainda é executada se necessário para que geradores subsequentes possam calcular o grafo de projetos Nx); instale uma vez no final. |
Saída do Gerador
Seção intitulada “Saída do Gerador”O gerador criará a seguinte estrutura de projeto no diretório <directory>/<name>:
- index.html HTML entry point
- public Static assets
Directorysrc
- main.tsx Application entry point with React setup
- config.ts Application configuration (eg. logo)
Directorycomponents
- AppLayout Components for the overall layout and navigation bar
Directoryhooks
- useAppLayout.tsx Hook for adjusting the AppLayout from nested components (Cloudscape only)
Directoryroutes
- 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
Infraestrutura
Seção intitulada “Infraestrutura”Como este gerador fornece infraestrutura como código baseada no seu iac escolhido, ele criará um projeto em packages/common que inclui os constructs CDK relevantes ou módulos Terraform.
O projeto comum de infraestrutura como código é estruturado da seguinte forma:
Directorypackages/common/constructs
Directorysrc
Directoryapp/ Constructs for infrastructure specific to a project/generator
- …
Directorycore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Directorypackages/common/terraform
Directorysrc
Directoryapp/ Terraform modules for infrastructure specific to a project/generator
- …
Directorycore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
O gerador cria infraestrutura como código para implantar seu site com base no iac selecionado:
Directorypackages/common/constructs/src
Directoryapp
Directorystatic-websites
- <name>.ts Infrastructure specific to your website
Directorycore
- static-website.ts Generic StaticWebsite construct
Directorypackages/common/terraform/src
Directoryapp
Directorystatic-websites
Directory<name>
- <name>.tf Module specific to your website
Directorycore
Directorystatic-website
- static-website.tf Generic static website module
Arquitetura
Seção intitulada “Arquitetura”O site implantado tem a seguinte arquitetura:
Implementando seu Site
Seção intitulada “Implementando seu Site”A documentação do React é um bom lugar para começar a aprender os conceitos básicos de construção com React.
Você pode consultar a documentação do Cloudscape para detalhes sobre os componentes disponíveis e como usá-los.
Você pode consultar a documentação do shadcn/ui para detalhes sobre os componentes disponíveis e como usá-los.
Criando uma Rota/Página
Seção intitulada “Criando uma Rota/Página”Seu site vem com TanStack Router configurado por padrão. Isso facilita a adição de novas rotas:
- Execute o Servidor de Desenvolvimento Local
- Crie um novo arquivo
<page-name>.tsxemsrc/routes, com sua posição na árvore de arquivos representando o caminho - Observe que um
RouteeRouteComponentsão gerados automaticamente para você. Você pode começar a construir sua página aqui!
Navegando Entre Páginas
Seção intitulada “Navegando Entre Páginas”Você pode usar o componente Link ou o 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 mais detalhes, confira a documentação do TanStack Router.
Implantando seu Site
Seção intitulada “Implantando seu Site”O gerador de site React cria infraestrutura como código CDK ou Terraform com base no iac selecionado. Você pode usar isso para implantar seu site.
Para implantar seu site, recomendamos usar o gerador ts#infra para criar uma aplicação CDK.
Você pode usar o construct CDK gerado para você em packages/common/constructs para implantar seu site.
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'); }}Isso configura:
- Um bucket S3 para hospedar seus arquivos de site estático
- Distribuição CloudFront para entrega global de conteúdo
- WAF Web ACL para proteção de segurança
- Origin Access Control para acesso seguro ao S3
- Implantação automática de arquivos do site e configuração de runtime
Para implantar seu site, recomendamos usar o gerador terraform#project para criar um projeto Terraform.
Você pode usar o módulo Terraform gerado para você em packages/common/terraform para implantar seu site.
# Deploy websitemodule "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 }}Isso configura:
- Um bucket S3 para hospedar seus arquivos de site estático
- Distribuição CloudFront para entrega global de conteúdo
- WAF Web ACL para proteção de segurança (implantado em us-east-1)
- Origin Access Control para acesso seguro ao S3
- Implantação automática de arquivos do site e configuração de runtime
Cabeçalhos de Segurança
Seção intitulada “Cabeçalhos de Segurança”A distribuição CloudFront aplica uma política de cabeçalhos de resposta que define Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options: DENY, Referrer-Policy e uma Content-Security-Policy em todas as respostas.
Uma Content-Security-Policy padrão é aplicada. Ela restringe scripts e framing para mitigar XSS e clickjacking, enquanto permite conexões HTTPS e WSS para que o site possa chamar endpoints de serviços AWS (como API Gateway, Cognito e Bedrock AgentCore) cujas URLs são conhecidas apenas no momento da implantação. Para ajustar a política (por exemplo, para restringir connect-src às suas origens específicas), edite o valor content_security_policy no seu static-website.ts (CDK) ou static-website.tf (Terraform) gerado.
runtime-config.json é servido com Cache-Control: no-cache para que os navegadores sempre busquem a configuração mais recente após uma reimplantação, em vez de usar uma cópia em cache desatualizada.
A distribuição CloudFront é protegida por um AWS WAFv2 Web ACL por padrão. O Web ACL usa o conjunto de regras padrão gerenciado pela AWS (AWSManagedRulesCommonRuleSet e AWSManagedRulesKnownBadInputsRuleSet), fornecendo proteção contra explorações web comuns, incluindo o OWASP Top 10.
Para desativar, defina enableWaf como false ao criar seu site:
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 desativar, defina enable_waf como 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}Criptografia de Bucket
Seção intitulada “Criptografia de Bucket”O bucket do site, o bucket de log da distribuição CloudFront e o grupo CloudWatch Logs que recebe seus logs de acesso ao servidor são criptografados com uma chave AWS KMS gerenciada pelo cliente por padrão. Esta chave é criada automaticamente para você, com rotação de chave habilitada.
Se você quiser usar uma configuração de criptografia diferente, passe as props encryption, encryptionKey e enableKeyRotation ao criar seu site:
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 sua própria chave KMS em vez de uma criada automaticamente, passe encryptionKey:
new MyWebsite(this, 'MyWebsite', { encryptionKey: myKey,});enableKeyRotation (padrão true) só se aplica à chave criada automaticamente, ou seja, quando encryption é BucketEncryption.KMS (o padrão) e nenhum encryptionKey é fornecido:
new MyWebsite(this, 'MyWebsite', { enableKeyRotation: false,});Se você quiser usar uma configuração de criptografia diferente, defina as variáveis encryption, kms_key_arn, create_kms_key e 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 sua própria chave KMS em vez de uma criada automaticamente, passe kms_key_arn e defina create_kms_key como 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}Uma chave fornecida pelo cliente já deve conceder aos principais de serviço CloudWatch Logs, S3 e CloudFront as permissões necessárias em sua própria política de chave.
enable_key_rotation (padrão true) só se aplica à chave criada automaticamente, ou seja, quando encryption é "KMS" (o padrão) e create_kms_key é 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}Domínio Personalizado e TLS
Seção intitulada “Domínio Personalizado e TLS”Por padrão, a distribuição usa o nome de domínio padrão do CloudFront (*.cloudfront.net) e seu certificado padrão, que não suporta a aplicação de uma versão TLS mínima de 1.2. Para servir seu site a partir do seu próprio domínio, forneça um certificado ACM (que deve residir em us-east-1 para uso com CloudFront) e seus nomes de domínio. Uma versão TLS mínima de 1.2 é então aplicada para os visualizadores:
Passe as props certificate e domainNames ao criar seu site:
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/...'), }); }}Defina as variáveis custom_domain_names e 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/..."}Você também precisará criar registros DNS (por exemplo, no Route 53) apontando seu domínio para a distribuição CloudFront.
Configuração de Runtime
Seção intitulada “Configuração de Runtime”A configuração da sua infraestrutura é fornecida ao seu site via Configuração de Runtime. Isso permite que seu site acesse detalhes como URLs de API que não são conhecidas até que sua aplicação seja implantada.
Infraestrutura
Seção intitulada “Infraestrutura”O construct CDK RuntimeConfig pode ser usado para adicionar e recuperar configuração em sua infraestrutura CDK. Os constructs CDK gerados pelos geradores @aws/nx-plugin (como ts#api e py#api) adicionarão automaticamente valores apropriados ao RuntimeConfig.
Seu construct CDK de site implantará o namespace connection da configuração de runtime como um arquivo runtime-config.json na raiz do seu 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(), }); }}Com Terraform, a configuração de runtime é gerenciada através dos módulos runtime-config. Os módulos Terraform gerados pelos geradores @aws/nx-plugin (como ts#api e py#api) adicionarão automaticamente valores apropriados à configuração de runtime.
Seu módulo Terraform de site implantará o namespace connection da configuração de runtime como um arquivo runtime-config.json na raiz do seu 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 do Site
Seção intitulada “Código do Site”No seu site, você pode usar o hook useRuntimeConfig para recuperar valores da configuração de runtime:
import { useRuntimeConfig } from '../hooks/useRuntimeConfig';
const MyComponent = () => { const runtimeConfig = useRuntimeConfig();
// Access values in the runtime config here const apiUrl = runtimeConfig.apis.MyApi;};Configuração de Runtime Local
Seção intitulada “Configuração de Runtime Local”Ao executar o servidor de desenvolvimento local, você precisará de um arquivo runtime-config.json no seu diretório public para que seu site local conheça as URLs de backend, configuração de identidade, etc.
Seu projeto de site está configurado com um target load-runtime-config que você pode usar para baixar o arquivo runtime-config.json de uma aplicação implantada:
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 Desenvolvimento Local
Seção intitulada “Servidor de Desenvolvimento Local”O comando canônico para desenvolvimento local é dev, que inicia seu site (e quaisquer servidores locais para APIs que você conectou a ele) com um único comando:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>O target serve também está disponível para quando você precisa controlar quanto da sua aplicação é executado localmente versus apontando para infraestrutura AWS implantada. Para uma visão geral mais ampla do desenvolvimento local em projetos conectados, incluindo como dev se comporta para projetos com múltiplos componentes, consulte o guia Desenvolvimento Local.
Target Serve
Seção intitulada “Target Serve”O target serve inicia um servidor de desenvolvimento local para seu site. Este target requer que você tenha implantado qualquer infraestrutura de suporte com a qual o site interage e tenha carregado a configuração de runtime local.
Você pode executar este target com o seguinte comando:
pnpm nx serve <my-website>yarn nx serve <my-website>npx nx serve <my-website>bunx nx serve <my-website>Este target é útil para trabalhar em alterações do site enquanto aponta para APIs “reais” implantadas e outra infraestrutura.
Target Dev
Seção intitulada “Target Dev”O target dev inicia um servidor de desenvolvimento local para seu site (com Vite MODE definido como local-dev), bem como inicia quaisquer servidores locais para APIs que você conectou ao seu site via o gerador Connection.
Quando seu servidor de site local é executado via este target, runtime-config.json é automaticamente substituído para apontar para suas URLs de API em execução local.
Você pode executar este target com o seguinte comando:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>Este target é útil quando você está trabalhando em seu site e API e deseja iterar rapidamente sem implantar sua infraestrutura.
Autenticação Simulada
Quando executado neste modo e nenhum runtime-config.json está presente, se você configurou Autenticação Cognito (via o gerador ts#website#auth), o login será ignorado e as solicitações aos seus servidores locais não incluirão cabeçalhos de autenticação.
Para habilitar login e autenticação para dev, implante sua infraestrutura e carregue a configuração de runtime.
Você pode fazer o build do seu site usando o target build. Isso executa os targets bundle, compile, test e lint, fazendo verificação de tipos, bundling, testes e linting do seu site.
pnpm nx build <my-website>yarn nx build <my-website>npx nx build <my-website>bunx nx build <my-website>O target bundle usa Vite para criar um bundle de produção no diretório raiz dist/packages/<my-website>/bundle. Este é o artefato implantável consumido pela sua infraestrutura de site. Você pode executá-lo sozinho:
pnpm nx bundle <my-website>yarn nx bundle <my-website>npx nx bundle <my-website>bunx nx bundle <my-website>Testar seu site é muito parecido com escrever testes em um projeto TypeScript padrão, então consulte o guia de projeto TypeScript para mais detalhes.
Para testes específicos do React, React Testing Library já está instalado e disponível para você usar para escrever testes. Para mais detalhes sobre seu uso, consulte a documentação do React Testing Library.
Você pode executar seus testes usando o target test:
pnpm nx test <my-website>yarn nx test <my-website>npx nx test <my-website>bunx nx test <my-website>Conexões
Seção intitulada “Conexões”Use o gerador connection para integrar este projeto com outros no seu workspace. As seguintes conexões envolvem este projeto:
