React 网站
此生成器创建一个新的 React 网站,默认配置了 shadcn/ui,以及用于将网站部署到云端的 AWS CDK 或 Terraform 基础设施,作为托管在 S3 中的静态网站,由 CloudFront 提供服务,并受 WAF 保护。
生成的应用程序使用 Vite 作为构建工具和打包器。它使用 TanStack Router 进行类型安全的路由。
生成 React 网站
Section titled “生成 React 网站”您可以通过两种方式生成新的 React 网站:
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=react您还可以执行试运行以查看哪些文件会被更改
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- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - ts#website - 填写必需参数
- framework: react
- 点击
Generate
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| name 必需 | string | - | 应用程序的名称。 |
| framework | react | react | 要使用的前端框架。 |
| directory | string | packages | 新应用程序的目录。 |
| subDirectory | string | - | 项目所在的子目录。默认情况下为项目名称。 |
| ux | none | cloudscape | shadcn | shadcn | 首选的 UX 提供商。 |
| tailwind | boolean | true | 启用 TailwindCSS 以实现实用优先的样式设计。 |
| tanstackRouter | boolean | true | 启用 Tanstack router 以实现类型安全的路由。 |
| infra | cloudfront-s3 | none | cloudfront-s3 | 用于部署网站的基础设施类型。 |
| iac | inherit | cdk | terraform | inherit | 首选的 IaC 提供商。默认情况下,这将继承您的初始选择。 |
| preferInstallDependencies | boolean | true | 是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。 |
生成器将在 <directory>/<name> 目录中创建以下项目结构:
- index.html HTML 入口点
- public 静态资源
文件夹src
- main.tsx 应用程序入口点,包含 React 设置
- config.ts 应用程序配置(例如 logo)
文件夹components
- AppLayout 整体布局和导航栏的组件
文件夹hooks
- useAppLayout.tsx 用于从嵌套组件调整 AppLayout 的钩子(仅限 Cloudscape)
文件夹routes
- index.tsx TanStack Router 的示例路由(或页面)
- styles.css 全局样式
- vite.config.mts Vite 和 Vitest 配置
- tsconfig.json 源代码和测试的基础 TypeScript 配置
- tsconfig.app.json 源代码的 TypeScript 配置
- tsconfig.spec.json 测试的 TypeScript 配置
- package.json 定义项目包名称和依赖项的项目清单
由于此生成器根据您选择的 iac 提供基础设施即代码,它将在 packages/common 中创建一个项目,其中包含相关的 CDK 构造或 Terraform 模块。
通用基础设施即代码项目的结构如下:
文件夹packages/common/constructs
文件夹src
文件夹app/ Constructs for infrastructure specific to a project/generator
- …
文件夹core/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
文件夹packages/common/terraform
文件夹src
文件夹app/ Terraform modules for infrastructure specific to a project/generator
- …
文件夹core/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
生成器根据您选择的 iac 创建用于部署网站的基础设施即代码:
文件夹packages/common/constructs/src
文件夹app
文件夹static-websites
- <name>.ts 特定于您网站的基础设施
文件夹core
- static-website.ts 通用 StaticWebsite 构造
文件夹packages/common/terraform/src
文件夹app
文件夹static-websites
文件夹<name>
- <name>.tf 特定于您网站的模块
文件夹core
文件夹static-website
- static-website.tf 通用静态网站模块
部署的网站具有以下架构:
实现您的网站
Section titled “实现您的网站”React 文档是学习使用 React 构建的基础知识的好地方。
您可以参考 Cloudscape 文档了解可用组件的详细信息以及如何使用它们。
您可以参考 shadcn/ui 文档了解可用组件的详细信息以及如何使用它们。
创建路由/页面
Section titled “创建路由/页面”您的网站默认配置了 TanStack Router。这使得添加新路由变得容易:
- 运行本地开发服务器
- 在
src/routes中创建一个新的<page-name>.tsx文件,其在文件树中的位置代表路径 - 注意
Route和RouteComponent会自动为您生成。您可以在这里开始构建您的页面!
在页面之间导航
Section titled “在页面之间导航”您可以使用 Link 组件或 useNavigate 钩子在页面之间导航:
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> </> )};有关更多详细信息,请查看 TanStack Router 文档。
部署您的网站
Section titled “部署您的网站”React 网站生成器根据您选择的 iac 创建 CDK 或 Terraform 基础设施即代码。您可以使用它来部署您的网站。
要部署您的网站,我们建议使用 ts#infra 生成器创建 CDK 应用程序。
您可以使用在 packages/common/constructs 中为您生成的 CDK 构造来部署您的网站。
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'); }}这将设置:
- 用于托管静态网站文件的 S3 存储桶
- 用于全球内容分发的 CloudFront 分配
- 用于安全保护的 WAF Web ACL
- 用于安全 S3 访问的源访问控制
- 自动部署网站文件和运行时配置
要部署您的网站,我们建议使用 terraform#project 生成器创建 Terraform 项目。
您可以使用在 packages/common/terraform 中为您生成的 Terraform 模块来部署您的网站。
# Deploy websitemodule "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 }}这将设置:
- 用于托管静态网站文件的 S3 存储桶
- 用于全球内容分发的 CloudFront 分配
- 用于安全保护的 WAF Web ACL(部署在 us-east-1)
- 用于安全 S3 访问的源访问控制
- 自动部署网站文件和运行时配置
CloudFront 分配应用响应标头策略,在所有响应上设置 Strict-Transport-Security、X-Content-Type-Options、X-Frame-Options: DENY、Referrer-Policy 和 Content-Security-Policy。
强制执行默认的 Content-Security-Policy。它限制脚本和框架以减轻 XSS 和点击劫持,同时允许 HTTPS 和 WSS 连接,以便网站可以调用 AWS 服务端点(如 API Gateway、Cognito 和 Bedrock AgentCore),这些 URL 仅在部署时才知道。要调整策略(例如将 connect-src 收紧到您的特定源),请编辑生成的 static-website.ts(CDK)或 static-website.tf(Terraform)中的 content_security_policy 值。
runtime-config.json 使用 Cache-Control: no-cache 提供服务,以便浏览器在重新部署后始终获取最新配置,而不是使用过时的缓存副本。
默认情况下,CloudFront 分配受 AWS WAFv2 Web ACL 保护。Web ACL 使用 AWS 托管的默认规则集(AWSManagedRulesCommonRuleSet 和 AWSManagedRulesKnownBadInputsRuleSet),提供针对常见 Web 漏洞(包括 OWASP Top 10)的保护。
要选择退出,在创建网站时将 enableWaf 设置为 false:
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', ); }}要选择退出,将 enable_waf 设置为 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}网站存储桶、CloudFront 分配日志存储桶以及接收其服务器访问日志的 CloudWatch Logs 组默认使用客户管理的 AWS KMS 密钥进行加密。此密钥会自动为您创建,并启用密钥轮换。
如果您想使用不同的加密配置,请在创建网站时传递 encryption、encryptionKey 和 enableKeyRotation 属性:
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, }); }}要使用您自己的 KMS 密钥而不是自动创建的密钥,请传递 encryptionKey:
new MyWebsite(this, 'MyWebsite', { encryptionKey: myKey,});enableKeyRotation(默认为 true)仅适用于自动创建的密钥,即当 encryption 为 BucketEncryption.KMS(默认值)且未提供 encryptionKey 时:
new MyWebsite(this, 'MyWebsite', { enableKeyRotation: false,});如果您想使用不同的加密配置,请设置 encryption、kms_key_arn、create_kms_key 和 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"}要使用您自己的 KMS 密钥而不是自动创建的密钥,请传递 kms_key_arn 并将 create_kms_key 设置为 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}客户提供的密钥必须在其自己的密钥策略中已经授予 CloudWatch Logs、S3 和 CloudFront 服务主体所需的权限。
enable_key_rotation(默认为 true)仅适用于自动创建的密钥,即当 encryption 为 "KMS"(默认值)且 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}自定义域名和 TLS
Section titled “自定义域名和 TLS”默认情况下,分配使用默认的 CloudFront 域名(*.cloudfront.net)及其默认证书,不支持强制执行最低 TLS 版本 1.2。要从您自己的域名提供网站服务,请提供 ACM 证书(必须位于 us-east-1 才能与 CloudFront 一起使用)和您的域名。然后为查看者强制执行最低 TLS 版本 1.2:
在创建网站时传递 certificate 和 domainNames 属性:
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/...'), }); }}设置 custom_domain_names 和 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/..."}您还需要创建 DNS 记录(例如在 Route 53 中)将您的域名指向 CloudFront 分配。
来自基础设施的配置通过运行时配置提供给您的网站。这允许您的网站访问诸如 API URL 之类的详细信息,这些信息在应用程序部署之前是未知的。
RuntimeConfig CDK 构造可用于在 CDK 基础设施中添加和检索配置。由 @aws/nx-plugin 生成器生成的 CDK 构造(如 ts#api 和 py#api)将自动向 RuntimeConfig 添加适当的值。
您的网站 CDK 构造将把运行时配置的 connection 命名空间作为 runtime-config.json 文件部署到 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(), }); }}使用 Terraform,运行时配置通过 runtime-config 模块管理。由 @aws/nx-plugin 生成器生成的 Terraform 模块(如 ts#api 和 py#api)将自动向运行时配置添加适当的值。
您的网站 Terraform 模块将把运行时配置的 connection 命名空间作为 runtime-config.json 文件部署到 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]}在您的网站中,您可以使用 useRuntimeConfig 钩子从运行时配置中检索值:
import { useRuntimeConfig } from '../hooks/useRuntimeConfig';
const MyComponent = () => { const runtimeConfig = useRuntimeConfig();
// Access values in the runtime config here const apiUrl = runtimeConfig.apis.MyApi;};本地运行时配置
Section titled “本地运行时配置”运行本地开发服务器时,您需要在 public 目录中有一个 runtime-config.json 文件,以便本地网站知道后端 URL、身份配置等。
您的网站项目配置了一个 load-runtime-config 目标,您可以使用它从已部署的应用程序中拉取 runtime-config.json 文件:
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>本地开发服务器
Section titled “本地开发服务器”本地开发的规范命令是 dev,它使用一个命令启动您的网站(以及您连接到它的任何 API 的本地服务器):
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>当您需要控制应用程序的多少部分在本地运行与指向已部署的 AWS 基础设施时,serve 目标也可用。有关跨连接项目的本地开发的更广泛概述,包括 dev 如何为具有多个组件的项目运行,请参阅本地开发指南。
Serve 目标
Section titled “Serve 目标”serve 目标为您的网站启动本地开发服务器。此目标要求您已部署网站交互的任何支持基础设施,并已加载本地运行时配置。
您可以使用以下命令运行此目标:
pnpm nx serve <my-website>yarn nx serve <my-website>npx nx serve <my-website>bunx nx serve <my-website>此目标对于在指向”真实”已部署的 API 和其他基础设施时处理网站更改很有用。
Dev 目标
Section titled “Dev 目标”dev 目标为您的网站启动本地开发服务器(Vite MODE 设置为 local-dev),并为您通过连接生成器连接到网站的任何 API 启动本地服务器。
当您的本地网站服务器通过此目标运行时,runtime-config.json 会自动覆盖以指向您本地运行的 API URL。
您可以使用以下命令运行此目标:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>当您跨网站和 API 工作并希望快速迭代而无需部署基础设施时,此目标很有用。
模拟身份验证
在此模式下运行且不存在 runtime-config.json 时,如果您已配置 Cognito 身份验证(通过 ts#website#auth 生成器),将跳过登录,并且对本地服务器的请求将不包含身份验证标头。
要为 dev 启用登录和身份验证,请部署您的基础设施并加载运行时配置。
您可以使用 build 目标构建您的网站。这会运行 bundle、compile、test 和 lint 目标,对您的网站进行类型检查、打包、测试和 lint。
pnpm nx build <my-website>yarn nx build <my-website>npx nx build <my-website>bunx nx build <my-website>bundle 目标使用 Vite 在根 dist/packages/<my-website>/bundle 目录中创建生产包。这是您的网站基础设施使用的可部署工件。您可以单独运行它:
pnpm nx bundle <my-website>yarn nx bundle <my-website>npx nx bundle <my-website>bunx nx bundle <my-website>测试您的网站与在标准 TypeScript 项目中编写测试非常相似,因此请参阅 TypeScript 项目指南了解更多详细信息。
对于 React 特定的测试,React Testing Library 已经安装并可供您使用来编写测试。有关其用法的更多详细信息,请参阅 React Testing Library 文档。
您可以使用 test 目标运行测试:
pnpm nx test <my-website>yarn nx test <my-website>npx nx test <my-website>bunx nx test <my-website>使用 connection 生成器将此项目与工作区中的其他项目集成。以下连接涉及此项目:
