React Website
Generator này tạo một website React mới với shadcn/ui được cấu hình mặc định, cùng với cơ sở hạ tầng AWS CDK hoặc Terraform để triển khai website của bạn lên cloud dưới dạng website tĩnh được lưu trữ trong S3, phục vụ bởi CloudFront và được bảo vệ bởi WAF.
Ứng dụng được tạo ra sử dụng Vite làm công cụ build và bundler. Nó sử dụng TanStack Router cho routing an toàn kiểu.
Cách sử dụng
Phần tiêu đề “Cách sử dụng”Tạo một React Website
Phần tiêu đề “Tạo một React Website”Bạn có thể tạo một React Website mới theo hai cách:
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=reactBạn cũng có thể thực hiện chạy thử để xem những tệp nào sẽ bị thay đổi
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- Cài đặt Nx Console VSCode Plugin nếu bạn chưa cài đặt
- Mở Nx Console trong VSCode
- Nhấp
Generate (UI)trong phần "Common Nx Commands" - Tìm kiếm
@aws/nx-plugin - ts#website - Điền các tham số bắt buộc
- framework: react
- Nhấp
Generate
Tùy chọn
Phần tiêu đề “Tùy chọn”| Tham số | Kiểu | Mặc định | Mô tả |
|---|---|---|---|
| name Bắt buộc | string | - | Tên của ứng dụng. |
| framework | react | react | Framework frontend sử dụng. |
| directory | string | packages | Thư mục của ứng dụng mới. |
| subDirectory | string | - | Thư mục con nơi dự án được đặt. Mặc định là tên dự án. |
| ux | none | cloudscape | shadcn | shadcn | Nhà cung cấp UX ưa thích. |
| tailwind | boolean | true | Bật TailwindCSS để tạo kiểu theo tiện ích. |
| tanstackRouter | boolean | true | Bật Tanstack router để định tuyến an toàn kiểu. |
| infra | cloudfront-s3 | none | cloudfront-s3 | Loại hạ tầng để triển khai website của bạn. |
| iac | inherit | cdk | terraform | inherit | Nhà cung cấp IaC ưa thích. Mặc định được kế thừa từ lựa chọn ban đầu của bạn. |
| preferInstallDependencies | boolean | true | Có nên cài đặt các dependencies sau khi generator chạy hay không. Đặt thành false để trì hoãn việc cài đặt khi chạy nhiều generator liên tiếp (việc cài đặt vẫn sẽ chạy nếu cần thiết để các generator tiếp theo có thể tính toán Nx project graph); cài đặt một lần vào cuối. |
Kết quả từ Generator
Phần tiêu đề “Kết quả từ Generator”Generator sẽ tạo cấu trúc dự án sau trong thư mục <directory>/<name>:
- index.html HTML entry point
- public Static assets
Thư mụcsrc
- main.tsx Application entry point with React setup
- config.ts Application configuration (eg. logo)
Thư mụccomponents
- AppLayout Components for the overall layout and navigation bar
Thư mụchooks
- useAppLayout.tsx Hook for adjusting the AppLayout from nested components (Cloudscape only)
Thư mụcroutes
- 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
Cơ sở hạ tầng
Phần tiêu đề “Cơ sở hạ tầng”Vì generator này cung cấp infrastructure as code dựa trên iac bạn đã chọn, nó sẽ tạo một dự án trong packages/common bao gồm các CDK constructs hoặc Terraform modules liên quan.
Dự án infrastructure as code chung được cấu trúc như sau:
Thư mụcpackages/common/constructs
Thư mụcsrc
Thư mụcapp/ Constructs for infrastructure specific to a project/generator
- …
Thư mụccore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Thư mụcpackages/common/terraform
Thư mụcsrc
Thư mụcapp/ Terraform modules for infrastructure specific to a project/generator
- …
Thư mụccore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
Generator tạo infrastructure as code để triển khai website của bạn dựa trên iac bạn đã chọn:
Thư mụcpackages/common/constructs/src
Thư mụcapp
Thư mụcstatic-websites
- <name>.ts Infrastructure specific to your website
Thư mụccore
- static-website.ts Generic StaticWebsite construct
Thư mụcpackages/common/terraform/src
Thư mụcapp
Thư mụcstatic-websites
Thư mục<name>
- <name>.tf Module specific to your website
Thư mụccore
Thư mụcstatic-website
- static-website.tf Generic static website module
Kiến trúc
Phần tiêu đề “Kiến trúc”Website được triển khai có kiến trúc như sau:
Triển khai Website của bạn
Phần tiêu đề “Triển khai Website của bạn”Tài liệu React là nơi tốt để bắt đầu học các kiến thức cơ bản về xây dựng với React.
Bạn có thể tham khảo tài liệu Cloudscape để biết chi tiết về các component có sẵn và cách sử dụng chúng.
Bạn có thể tham khảo tài liệu shadcn/ui để biết chi tiết về các component có sẵn và cách sử dụng chúng.
Routes
Phần tiêu đề “Routes”Tạo một Route/Page
Phần tiêu đề “Tạo một Route/Page”Website của bạn đi kèm với TanStack Router được cấu hình mặc định. Điều này giúp dễ dàng thêm các route mới:
- Chạy Local Development Server
- Tạo một file
<page-name>.tsxmới trongsrc/routes, với vị trí của nó trong cây file đại diện cho đường dẫn - Lưu ý rằng một
RoutevàRouteComponentđược tự động tạo cho bạn. Bạn có thể bắt đầu xây dựng trang của mình tại đây!
Điều hướng giữa các Trang
Phần tiêu đề “Điều hướng giữa các Trang”Bạn có thể sử dụng component Link hoặc hook useNavigate để điều hướng giữa các trang:
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> </> )};Để biết thêm chi tiết, hãy xem tài liệu TanStack Router.
Triển khai Website của bạn
Phần tiêu đề “Triển khai Website của bạn”Generator React website tạo infrastructure as code CDK hoặc Terraform dựa trên iac bạn đã chọn. Bạn có thể sử dụng nó để triển khai website của mình.
Để triển khai website của bạn, chúng tôi khuyến nghị sử dụng generator ts#infra để tạo một ứng dụng CDK.
Bạn có thể sử dụng CDK construct được tạo cho bạn trong packages/common/constructs để triển khai website của mình.
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'); }}Điều này thiết lập:
- Một S3 bucket để lưu trữ các file website tĩnh của bạn
- CloudFront distribution để phân phối nội dung toàn cầu
- WAF Web ACL để bảo vệ bảo mật
- Origin Access Control để truy cập S3 an toàn
- Tự động triển khai các file website và cấu hình runtime
Để triển khai website của bạn, chúng tôi khuyến nghị sử dụng generator terraform#project để tạo một dự án Terraform.
Bạn có thể sử dụng module Terraform được tạo cho bạn trong packages/common/terraform để triển khai website của mình.
# Deploy websitemodule "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 }}Điều này thiết lập:
- Một S3 bucket để lưu trữ các file website tĩnh của bạn
- CloudFront distribution để phân phối nội dung toàn cầu
- WAF Web ACL để bảo vệ bảo mật (được triển khai trong us-east-1)
- Origin Access Control để truy cập S3 an toàn
- Tự động triển khai các file website và cấu hình runtime
Security Headers
Phần tiêu đề “Security Headers”CloudFront distribution áp dụng chính sách response headers thiết lập Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options: DENY, Referrer-Policy và một Content-Security-Policy trên tất cả các response.
Một Content-Security-Policy mặc định được thực thi. Nó hạn chế scripts và framing để giảm thiểu XSS và clickjacking, trong khi cho phép kết nối HTTPS và WSS để website có thể gọi các endpoint dịch vụ AWS (như API Gateway, Cognito và Bedrock AgentCore) mà URL chỉ được biết tại thời điểm triển khai. Để điều chỉnh chính sách (ví dụ: để thắt chặt connect-src cho các origin cụ thể của bạn), hãy chỉnh sửa giá trị content_security_policy trong static-website.ts (CDK) hoặc static-website.tf (Terraform) được tạo của bạn.
runtime-config.json được phục vụ với Cache-Control: no-cache để trình duyệt luôn lấy cấu hình mới nhất sau khi triển khai lại, thay vì sử dụng bản sao được cache cũ.
CloudFront distribution được bảo vệ bởi một AWS WAFv2 Web ACL theo mặc định. Web ACL sử dụng bộ quy tắc mặc định được quản lý bởi AWS (AWSManagedRulesCommonRuleSet và AWSManagedRulesKnownBadInputsRuleSet), cung cấp bảo vệ chống lại các khai thác web phổ biến bao gồm OWASP Top 10.
Để từ chối, đặt enableWaf thành false khi bạn tạo website của mình:
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', ); }}Để từ chối, đặt enable_waf thành 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}Bucket Encryption
Phần tiêu đề “Bucket Encryption”Website bucket, CloudFront distribution log bucket, và CloudWatch Logs group nhận server access logs của chúng được mã hóa bằng khóa AWS KMS do khách hàng quản lý theo mặc định. Khóa này được tạo tự động cho bạn, với tính năng xoay khóa được bật.
Nếu bạn muốn sử dụng cấu hình mã hóa khác, hãy truyền các props encryption, encryptionKey và enableKeyRotation khi bạn tạo website của mình:
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, }); }}Để sử dụng khóa KMS của riêng bạn thay vì khóa được tạo tự động, hãy truyền encryptionKey:
new MyWebsite(this, 'MyWebsite', { encryptionKey: myKey,});enableKeyRotation (mặc định true) chỉ áp dụng cho khóa được tạo tự động, tức là khi encryption là BucketEncryption.KMS (mặc định) và không có encryptionKey được cung cấp:
new MyWebsite(this, 'MyWebsite', { enableKeyRotation: false,});Nếu bạn muốn sử dụng cấu hình mã hóa khác, hãy đặt các biến encryption, kms_key_arn, create_kms_key và 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"}Để sử dụng khóa KMS của riêng bạn thay vì khóa được tạo tự động, hãy truyền kms_key_arn và đặt create_kms_key thành 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}Một khóa do khách hàng cung cấp phải đã cấp cho các service principals CloudWatch Logs, S3 và CloudFront các quyền mà chúng cần trong chính sách khóa của chính nó.
enable_key_rotation (mặc định true) chỉ áp dụng cho khóa được tạo tự động, tức là khi encryption là "KMS" (mặc định) và create_kms_key là 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}Custom Domain & TLS
Phần tiêu đề “Custom Domain & TLS”Theo mặc định, distribution sử dụng tên miền CloudFront mặc định (*.cloudfront.net) và chứng chỉ mặc định của nó, không hỗ trợ thực thi phiên bản TLS tối thiểu là 1.2. Để phục vụ website của bạn từ tên miền của riêng bạn, hãy cung cấp một chứng chỉ ACM (phải nằm trong us-east-1 để sử dụng với CloudFront) và tên miền của bạn. Phiên bản TLS tối thiểu là 1.2 sau đó được thực thi cho người xem:
Truyền các props certificate và domainNames khi bạn tạo website của mình:
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/...'), }); }}Đặt các biến custom_domain_names và 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/..."}Bạn cũng sẽ cần tạo các bản ghi DNS (ví dụ trong Route 53) trỏ tên miền của bạn đến CloudFront distribution.
Runtime Configuration
Phần tiêu đề “Runtime Configuration”Cấu hình từ cơ sở hạ tầng của bạn được cung cấp cho website của bạn qua Runtime Configuration. Điều này cho phép website của bạn truy cập các chi tiết như API URLs mà không được biết cho đến khi ứng dụng của bạn được triển khai.
Cơ sở hạ tầng
Phần tiêu đề “Cơ sở hạ tầng”CDK construct RuntimeConfig có thể được sử dụng để thêm và truy xuất cấu hình trong cơ sở hạ tầng CDK của bạn. Các CDK constructs được tạo bởi các generators @aws/nx-plugin (như ts#api và py#api) sẽ tự động thêm các giá trị thích hợp vào RuntimeConfig.
CDK construct website của bạn sẽ triển khai namespace connection của runtime configuration dưới dạng file runtime-config.json vào thư mục gốc của S3 bucket của bạn.
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(), }); }}Với Terraform, runtime configuration được quản lý thông qua các runtime-config modules. Các Terraform modules được tạo bởi các generators @aws/nx-plugin (như ts#api và py#api) sẽ tự động thêm các giá trị thích hợp vào runtime configuration.
Terraform module website của bạn sẽ triển khai namespace connection của runtime configuration dưới dạng file runtime-config.json vào thư mục gốc của S3 bucket của bạn.
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]}Website Code
Phần tiêu đề “Website Code”Trong website của bạn, bạn có thể sử dụng hook useRuntimeConfig để truy xuất các giá trị từ runtime configuration:
import { useRuntimeConfig } from '../hooks/useRuntimeConfig';
const MyComponent = () => { const runtimeConfig = useRuntimeConfig();
// Access values in the runtime config here const apiUrl = runtimeConfig.apis.MyApi;};Local Runtime Config
Phần tiêu đề “Local Runtime Config”Khi chạy local development server, bạn sẽ cần một file runtime-config.json trong thư mục public của bạn để website local của bạn biết các backend URLs, cấu hình identity, v.v.
Dự án website của bạn được cấu hình với target load-runtime-config mà bạn có thể sử dụng để tải xuống file runtime-config.json từ một ứng dụng đã triển khai:
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>Local Development Server
Phần tiêu đề “Local Development Server”Lệnh chính thức cho phát triển local là dev, khởi động website của bạn (và bất kỳ local servers nào cho các APIs bạn đã kết nối nó) bằng một lệnh:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>Target serve cũng có sẵn cho khi bạn cần kiểm soát bao nhiêu ứng dụng của bạn chạy locally so với trỏ đến cơ sở hạ tầng AWS đã triển khai. Để có cái nhìn tổng quan rộng hơn về phát triển local trên các dự án được kết nối, bao gồm cách dev hoạt động cho các dự án với nhiều components, hãy xem hướng dẫn Local Development.
Serve Target
Phần tiêu đề “Serve Target”Target serve khởi động một local development server cho website của bạn. Target này yêu cầu bạn đã triển khai bất kỳ cơ sở hạ tầng hỗ trợ nào mà website tương tác với, và đã tải local runtime configuration.
Bạn có thể chạy target này với lệnh sau:
pnpm nx serve <my-website>yarn nx serve <my-website>npx nx serve <my-website>bunx nx serve <my-website>Target này hữu ích cho việc làm việc trên các thay đổi website trong khi trỏ đến các APIs “thực” đã triển khai và cơ sở hạ tầng khác.
Dev Target
Phần tiêu đề “Dev Target”Target dev khởi động một local development server cho website của bạn (với Vite MODE được đặt thành local-dev), cũng như khởi động bất kỳ local servers nào cho các APIs bạn đã kết nối website của mình qua Connection generator.
Khi local website server của bạn được chạy qua target này, runtime-config.json được tự động ghi đè để trỏ đến các locally running API urls của bạn.
Bạn có thể chạy target này với lệnh sau:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>Target này hữu ích khi bạn đang làm việc trên website và API của mình và muốn lặp lại nhanh chóng mà không cần triển khai cơ sở hạ tầng của bạn.
Mock Authentication
Khi chạy ở chế độ này và không có runtime-config.json, nếu bạn đã cấu hình Cognito Authentication (qua generator ts#website#auth), đăng nhập sẽ được bỏ qua và các yêu cầu đến local servers của bạn sẽ không bao gồm authentication headers.
Để bật đăng nhập và xác thực cho dev, hãy triển khai cơ sở hạ tầng của bạn và tải runtime config.
Building
Phần tiêu đề “Building”Bạn có thể build website của mình bằng target build. Điều này chạy các targets bundle, compile, test và lint, type-checking, bundling, testing và linting website của bạn.
pnpm nx build <my-website>yarn nx build <my-website>npx nx build <my-website>bunx nx build <my-website>Target bundle sử dụng Vite để tạo một production bundle trong thư mục gốc dist/packages/<my-website>/bundle. Đây là artifact có thể triển khai được sử dụng bởi cơ sở hạ tầng website của bạn. Bạn có thể chạy nó một mình:
pnpm nx bundle <my-website>yarn nx bundle <my-website>npx nx bundle <my-website>bunx nx bundle <my-website>Testing
Phần tiêu đề “Testing”Kiểm thử website của bạn giống như viết tests trong một dự án TypeScript tiêu chuẩn, vì vậy vui lòng tham khảo hướng dẫn dự án TypeScript để biết thêm chi tiết.
Đối với kiểm thử cụ thể của React, React Testing Library đã được cài đặt và có sẵn để bạn sử dụng để viết tests. Để biết thêm chi tiết về cách sử dụng, vui lòng tham khảo tài liệu React Testing Library.
Bạn có thể chạy tests của mình bằng target test:
pnpm nx test <my-website>yarn nx test <my-website>npx nx test <my-website>bunx nx test <my-website>Connections
Phần tiêu đề “Connections”Sử dụng generator connection để tích hợp dự án này với các dự án khác trong workspace của bạn. Các connections sau liên quan đến dự án này:
