10 releases
new 0.6.4 | Nov 4, 2024 |
---|---|
0.6.3 | Nov 4, 2024 |
0.6.2 | Oct 23, 2024 |
0.6.0-alpha.2 | Sep 29, 2024 |
0.5.3 | Sep 18, 2024 |
#1022 in Network programming
561 downloads per month
19KB
213 lines
Dioxus AWS
dioxus-aws
crate provides a launch
function to make dioxus
run on AWS Serverless Stack (AWS Lambda, CloudFront and S3).
Development
Creating a project
- Use
dx
command.- Currently,
dioxus-cli v0.5
, which is stable version of dioxus, is supported.
- Currently,
cargo install dioxus-cli --version ^0.5
dx new --subtemplate Fullstack project-name
Re-Writing main
function
Installing dependancy
- Add
dioxus-aws
.
cargo add dioxus-aws
main
function
- Change
launch(App)
todioxus_aws::launch(App)
.
dioxus_aws::launch(App); // launch(App);
Running and testing the project
- It is same with usage of
dioxus-cli
.
cargo add dioxus-aws
dx serve --platform fullstack
Deployment
It uses AWS Lambda, S3 and CloudFront to deploy dixous application.
Setup AWS CDK
- Setup AWS CDK to deploy application.
- For more information about AWS CDK, refer to AWS CDK Guide
- For basic tutorial of AWS CDK, refer to the tutorial
npm install -g aws-cdk
mkdir -p fixtures/aws-cdk
cd fixtures/aws-cdk
cdk init app --language=typescript
Writing CDK Stack
Route53
sets up a domain to CloudFront.CloudFront
distributes requests to API Gateway or S3.API Gateway
is bound to AWS Lambda.S3
stores assets like js, html, images and so on.
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as acm from "aws-cdk-lib/aws-certificatemanager";
import * as route53 from "aws-cdk-lib/aws-route53";
import * as targets from "aws-cdk-lib/aws-route53-targets";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
export class AwsCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const domain = process.env.DOMAIN || "";
const acmId = process.env.ACM_ID || "";
const hostedZoneId = process.env.HOSTED_ZONE_ID || "";
const projectRoot = process.env.PROJECT_ROOT || "";
const assetsBucket = new s3.Bucket(this, "Bucket", {
bucketName: domain,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
const certificate = acm.Certificate.fromCertificateArn(
this,
"Certificate",
acmId,
);
const func = new lambda.Function(this, "Function", {
runtime: lambda.Runtime.PROVIDED_AL2023,
code: lambda.Code.fromAsset(projectRoot + "/dist"),
handler: "bootstrap",
environment: {
NO_COLOR: "true",
ASSETS_PATH: "./",
},
memorySize: 128,
});
const api = new apigateway.LambdaRestApi(this, "Api", {
handler: func,
proxy: true,
});
const s3Origin = new origins.S3Origin(assetsBucket);
const apiOrigin = new origins.RestApiOrigin(api);
const cf = new cloudfront.Distribution(this, "Distribution", {
defaultBehavior: {
origin: apiOrigin,
cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
originRequestPolicy:
cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
},
additionalBehaviors: {
"/assets/*": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
"/*.js": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
"/*.css": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
"/*.html": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
"/*.ico": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
"/*.svg": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
"/icons/*": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
"/images/*": {
origin: s3Origin,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
},
domainNames: [domain],
certificate,
});
const zone = route53.HostedZone.fromHostedZoneAttributes(
this,
"zone-attribute",
{
zoneName: domain,
hostedZoneId,
},
);
new route53.ARecord(this, "IpV4Record", {
zone,
target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(cf)),
});
new route53.AaaaRecord(this, "IpV6Record", {
zone,
target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(cf)),
});
}
}
Build and deploy application
Building a binary for AWS Lambda
- Note that
server-feature
is set tolambda
instead ofserver
. - Then, rename binary to
bootstrap
.- Usually,
SERVICE
might bebasename $(git rev-parse --show-toplevel)
.
- Usually,
export SERVICE=$(cargo tree | head -n 1 | awk '{print $1}')
dx build --release --platform fullstack --server-feature lambda
mv dist/$SERVICE dist/bootstrap
Deploy AWS CDK
- Let you remember environments in CDK Stack.
DOMAIN
is FQDN including subdomain.ACM_ID
must be placed inus-east-1
for CloudFront.HOSTED_ZONE_ID
is a zone ID of Route53.PROJECT_ROOT
is a path of project root.
export DOMAIN="dioxus.example.com"
export ACM_ID="arn:aws:acm:us-east-1:---"
export HOSTED_ZONE_ID="Z--"
export PROJECT_ROOT=$(pwd)
export AWS_PROFILE=default
cd fixtures/aws-cdk
npm run build
cdk synth
cdk bootstrap --profile $AWS_PROFILE
# AWS Stack deployment
cdk deploy --require-approval never --profile $AWS_PROFILE
# S3 Assets sync
aws s3 sync $PROJECT_ROOT/dist/public s3://$DOMAIN --delete --profile $AWS_PROFILE
Dependencies
~15–29MB
~438K SLoC