- Newest
- Most votes
- Most comments
Hi Emmanuel,
Thank you for your detailed question! It’s great that you’re exploring AWS Amplify Gen 2 for deploying your monolithic application. Let’s break this down step by step with detailed code examples and additional context to help you implement the solution smoothly.
Clarifying the Issue
You have a monolithic application that needs to run on AWS Amplify Gen 2. The application includes both a frontend (served from the /build directory) and a backend (served from the /dist directory). The server uses Hono for the API and React (via Vite) for the frontend. You are trying to serve both frontend and backend components simultaneously under the same domain, specifically ensuring that API routes like /api work as intended.
Currently, AWS Amplify mandates choosing a single build directory, which leads to the backend not being accessible since it serves only the frontend.
Key Terms
- AWS Amplify Gen 2: A hosting service for modern web apps, offering integration with CI/CD and serverless resources.
- Hono: A lightweight, high-performance web framework.
- React: A JavaScript library for building user interfaces, often used for single-page applications.
- Vite: A modern frontend build tool optimized for speed and developer experience.
- Monolithic Application: An architecture where the frontend, backend, and API are combined in a single codebase or deployment.
The Solution (Our Recipe)
Steps at a Glance:
- Separate frontend and backend builds into distinct deployment workflows.
- Deploy the frontend with Amplify and use Amazon API Gateway for the backend API routes.
- Configure custom domain routing for seamless integration of frontend and backend services.
- Integrate frontend and backend.
Step-by-Step Guide:
1. Separate Frontend and Backend Builds
Why this step?
Separating the builds allows Amplify to handle the static frontend, while the backend is managed by a service more suited for dynamic requests, like AWS Lambda or API Gateway.
Code Example: Update your package.json to define separate build scripts for the frontend and backend:
"scripts": { "build:frontend": "vite build", "build:backend": "tsc && rollup -c rollup.config.mjs" }
Then run the following commands to generate builds for both:
npm run build:frontend npm run build:backend
Resulting Directory Structure:
project-root/
├── build/ # Frontend build output
├── dist/ # Backend build output
├── src/ # Source code
├── package.json
└── rollup.config.mjs
2. Deploy Frontend with Amplify
Why this step?
Amplify Hosting is optimized for static files (e.g., frontend build outputs). It’s ideal for serving React applications with minimal effort.
Amplify Configuration:
In the Amplify Console, specify the build directory as the artifact base directory. Add an amplify.yml to your repository for the frontend build:
version: 1 frontend: phases: preBuild: commands: - npm ci build: commands: - npm run build:frontend artifacts: baseDirectory: /build files: - '**/*' cache: paths: - node_modules/**/*
Commit this file to your repository, connect the repository to Amplify Hosting, and Amplify will automatically build and deploy your frontend.
3. Deploy Backend Using Amazon API Gateway
Why this step?
API Gateway is ideal for managing API routes, providing flexibility for dynamic backend logic and integration with Lambda functions.
Code Example: Create a Lambda function for your backend:
import { app } from './dist/app.js'; export const handler = async (event) => { return await app.fetch(event); };
Deploy the backend using the AWS CLI:
zip -r backend.zip ./dist aws lambda create-function --function-name myBackendAPI \ --runtime nodejs18.x \ --role <your-lambda-execution-role> \ --handler index.handler \ --zip-file fileb://backend.zip
Set Up API Gateway:
- Create an HTTP API:
aws apigatewayv2 create-api \ --name MyAPI \ --protocol-type HTTP \ --target arn:aws:lambda:<region>:<account-id>:function:myBackendAPI - Add a route for
/api:aws apigatewayv2 create-route \ --api-id <api-id> \ --route-key "ANY /api/{proxy+}" aws apigatewayv2 create-integration \ --api-id <api-id> \ --integration-type AWS_PROXY \ --integration-uri arn:aws:lambda:<region>:<account-id>:function:myBackendAPI - Grant Lambda Permissions:
aws lambda add-permission \ --function-name myBackendAPI \ --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn arn:aws:execute-api:<region>:<account-id>:<api-id>/*
4. Integrate Frontend and Backend
Why this step?
To ensure the frontend and backend work seamlessly under the same domain, you need to configure Amplify's custom domain settings so /api requests are routed to the backend hosted on API Gateway.
Custom Domain Setup in Amplify Console:
-
Add a Custom Domain:
In the Amplify Console:- Go to the "Domain management" section of your app.
- Add your custom domain (e.g.,
example.com) and follow the prompts to verify ownership through your DNS provider.
-
Add Rewrite and Redirect Rules:
Configure rules to redirect/apiroutes to your API Gateway endpoint. Add a rule like this:Source Address Target Address Type Status Code /api/<*>https://<api-id>.execute-api.<region>.amazonaws.com/<*>Rewrite 200 -
Environment Variables for Dynamic API Integration:
Add the following variable in your Amplifyamplify.ymlfile to dynamically configure the API endpoint:frontend: environment: REACT_APP_API_URL: "https://<api-id>.execute-api.<region>.amazonaws.com"
React Code Example (With Custom Domain):
Your React app can now use the /api endpoint seamlessly:
const API_URL = process.env.REACT_APP_API_URL || '/api'; const fetchData = async () => { const response = await fetch(`${API_URL}/example-endpoint`); const data = await response.json(); console.log(data); }; fetchData();
Closing Thoughts
By following this approach, you leverage the strengths of AWS services: Amplify Hosting for static assets, API Gateway for dynamic backend routing, and Lambda for serverless compute. This hybrid solution ensures a seamless and scalable deployment of your monolithic application.
Feel free to share updates or reach out if you have further questions, Emmanuel. You’re on the right track, and I’m here to help if needed! 😊✨
Take care, Emmanuel, and happy coding! 🚀
Cheers, Aaron 😊✨
Relevant content
- AWS OFFICIALUpdated 4 years ago
- AWS OFFICIALUpdated 3 months ago
