cdk-nuxt
v2.3.1
Published
<p> <a href="https://github.com/ferdinandfrank/cdk-nuxt/actions/workflows/publish.yml"><img alt="Build" src="https://img.shields.io/github/actions/workflow/status/ferdinandfrank/cdk-nuxt/publish.yml?logo=github" /></a> <a href="https://www.npmjs.com/packa
Downloads
71
Readme
AWS CDK Nuxt 3 Deployment Stack
Easily deploy Nuxt 3 applications via CDK on AWS including the following features:
- Fast responses via AWS Lambda
- Publicly available by a custom domain (or subdomain) via Route53 and API Gateway
- Automatic redirects from HTTP to HTTPS via CloudFront
- Automatic upload of the build files for CSR and static assets to S3 with optimized caching rules
- Scheduled pings of the Nuxt app to keep the Lambda warm for fast responses via EventBridge rules
- Automatic cleanup of outdated static assets and build files
- Access logs analysis via Athena for the Nuxt app's CloudFront distribution
Prerequisites
- This package currently relies on using Yarn instead of NPM for deployment. Therefore, make sure to have Yarn available on the deployment system.
- You need an AWS account to create and deploy the required resources for the Nuxt app on AWS.
Installation
Install the package and its required dependencies:
yarn add cdk-nuxt --dev # The package itself
yarn add ts-node typescript --dev # To compile the CDK stacks via typescript
yarn add [email protected] --dev # CDK cli with this exact version for the deployment
Setup
Set the Nitro preset on your Nuxt configuration file (
nuxt.config.js
) toaws-lambda
:export default defineNuxtConfig({ ... nitro: { preset: 'aws-lambda' }, ... });
See https://nitro.unjs.io/deploy/providers/aws for more details.
Remove
"type": "module"
from yourpackage.json
file, if it exists. This is required to make the CDK stack work. Click here for details.Create an AWS account, if you don't have one yet. Then login into the AWS console and note the
Account ID
. You will need it in step 7.Create a hosted zone in Route53 for the desired domain, if you don't have one yet.This is required to create DNS records for the domain to make the Nuxt app publicly available on that domain.On the hosted zone details you should see the
Hosted zone ID
of the hosted zone. You will need it in step 7.Request a public regional certificate in the AWS Certificate Manager (ACM) for the desired domain in your desired region, e.g.,
eu-central-1
, and validate it, if you don't have one yet.This is required to make the Nuxt app accessible via the custom domain and to provide the custom domain to the Nuxt app via the 'Host' header for server side rendering use cases.Take note of the displayedARN
for the certificate. You will need it in step 7.Request a public global certificate in the AWS Certificate Manager (ACM) for the desired domain in
us-east-1
(global) and validate it, if you don't have one yet.This is required to provide the Nuxt app via HTTPS on the public internet.Take note of the displayedARN
for the certificate. You will need it in step 7.Important: The certificate must be issued in us-east-1 (global) regardless of the region used for the Nuxt app itself as it will be attached to the Cloudfront distribution which works globally.Run the following command to automatically create the required CDK stack entrypoint at
stack/index.ts
. This file defines the config how the Nuxt app will be deployed via CDK. You should adapt the file to the project's needs, especially the propsenv.account
(setup step 3),hostedZoneId
(setup step 4),regionalTlsCertificateArn
(setup step 5) andglobalTlsCertificateArn
(setup step 6).node_modules/.bin/cdk-nuxt-init-server
:warning: It's recommended using a
.env
file or another secrets file to import the sensitive secrets into thestack/index.ts
file.
Configuration
The NuxtServerAppStack
construct can be configured via the following props:
project: string
A string identifier for the project the Nuxt app is part of. A project might have multiple different services.
service: string
A string identifier for the project's service the Nuxt app is created for. This can be seen as the name of the Nuxt app.
environment: string
A string to identify the environment of the Nuxt app. This enables us to deploy multiple different environments of the same Nuxt app, e.g., production and development.
domain: string
The domain (without the protocol) at which the Nuxt app shall be publicly available. A DNS record will be automatically created in Route53 for the domain. This also supports subdomains. Examples: "example.com", "sub.example.com"
hostedZoneId: string
The id of the hosted zone to create a DNS record for the specified domain.
globalTlsCertificateArn: string
The ARN of the certificate to use on CloudFront for the Nuxt app to make it accessible via HTTPS. The certificate must be issued for the specified domain in us-east-1 (global) regardless of the region specified via 'env.region' as CloudFront only works globally.
regionalTlsCertificateArn: string
The ARN of the certificate to use at the ApiGateway for the Nuxt app to make it accessible via the custom domain and to provide the custom domain to the Nuxt app via the 'Host' header for server side rendering use cases. The certificate must be issued in the same region as specified via 'env.region' as ApiGateway works regionally.
rootDir?: string;
The path to the root directory of the Nuxt app (at which the nuxt.config.ts
file is located).
Defaults to '.'.
entrypoint?: string
The file name (without extension) of the Lambda entrypoint within the 'server' directory exporting a handler. Defaults to "index".
entrypointEnv?: string
A JSON serialized string of environment variables to pass to the Lambda function.
memorySize?: number
The memory size to apply to the Nuxt app's Lambda. Defaults to 1792MB (optimized for costs and performance for standard Nuxt apps).
enableTracing?: boolean
Whether to enable AWS X-Ray for the Nuxt Lambda function.
enableApi?: boolean
Whether to enable (HTTPS only) API access to the Nuxt app via the /api
path which support all HTTP methods.
See https://nuxt.com/docs/guide/directory-structure/server#recipes for details.
enableSitemap?: boolean
Whether to enable a global Sitemap bucket which is permanently accessible through multiple deployments.
enableAccessLogsAnalysis?: boolean
Whether to enable access logs analysis for the Nuxt app's CloudFront distribution via Athena.
accessLogCookies?: string[]
An array of cookies to include for reporting in the access logs analysis.
Only has an effect when enableAccessLogsAnalysis
is set to true
.
outdatedAssetsRetentionDays?: boolean
The number of days to retain static assets of outdated deployments in the S3 bucket. Useful to allow users to still access old assets after a new deployment when they are still browsing on an old version. Defaults to 30 days.
allowHeaders?: string[]
An array of headers to pass to the Nuxt app on SSR requests. The more headers are passed, the weaker the cache performance will be, as the cache key is based on the headers. No headers are passed by default.
allowCookies?: string[]
An array of cookies to pass to the Nuxt app on SSR requests. The more cookies are passed, the weaker the cache performance will be, as the cache key is based on the cookies. No cookies are passed by default.
allowQueryParams?: string[]
An array of query param keys to pass to the Nuxt app on SSR requests. The more query params are passed, the weaker the cache performance will be, as the cache key is based on the query params. Note that this config can not be combined with {@see denyQueryParams}. If both are specified, the {@see denyQueryParams} will be ignored. All query params are passed by default.
denyQueryParams?: string[]
An array of query param keys to deny passing to the Nuxt app on SSR requests. It might be useful to prevent specific external query params, e.g., fbclid, utm_campaign, ..., to improve cache performance, as the cache key is based on the specified query params. Note that this config can not be combined with {@see allowQueryParams}. If both are specified, the {@see denyQueryParams} will be ignored. All query params are passed by default.
Deployment
After the installation and the setup you are already good to go to build the Nuxt app and to deploy it to AWS with this package by following the steps below:
1. Bootstrap CDK
Deploying stacks with the AWS CDK requires dedicated Amazon S3 buckets and other containers to be available to AWS CloudFormation during deployment. Creating these is called bootstrapping and is only required once per account and region. To bootstrap, run the following command:
cdk bootstrap aws://ACCOUNT-NUMBER/REGION
See https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html for details.
2. Build and Deploy
By running the following script, the Nuxt app will be built automatically via yarn build
and the CDK stack will be deployed to AWS.
node_modules/.bin/cdk-nuxt-deploy-server
Alternatively, you can run the following commands separately to customize the deployment process:
yarn build
yarn cdk deploy --require-approval never --all --app="yarn ts-node stack/index.ts"
Destroy the Stack
If you want to destroy the stack and all its resources (including storage, e.g., access logs), run the following script:
node_modules/.bin/cdk-nuxt-destroy-server
Reference: Created AWS Resources
In the following, you can find an overview of the AWS resources that will be created by this package for reference.
NuxtServerAppStack
This stack is responsible for deploying dynamic Nuxt 3 apps to AWS. The following AWS resources will be created by this stack:
- Lambda:
- A Lambda function to render the Nuxt app including a separated Lambda layer to provide the
node_modules
of the Nuxt app required for server-side rendering. - A Lambda function that deletes the outdated static assets of the Nuxt app from S3.
- A Lambda function to render the Nuxt app including a separated Lambda layer to provide the
- S3:
- A bucket to store the client files and static assets of the Nuxt build (
.nuxt/dist/client
) with optimized cache settings. - A bucket to store the CloudFront access logs for analysis via Athena. Only created if
enableAccessLogsAnalysis
is set totrue
.
- A bucket to store the client files and static assets of the Nuxt build (
- Route53: Two DNS records (
A
for IPv4 andAAAA
for IPv6) in the configured hosted zone to make the Nuxt app available on the internet via the configured custom domain. - API Gateway: An HTTP API to make the Nuxt Lambda function publicly available.
- CloudFront: A distribution to route incoming requests to the Nuxt Lambda function (via the API Gateway) and the S3 bucket to serve the static assets for the Nuxt app.
- EventBridge:
- A scheduled rule to ping the Nuxt app's Lambda function every 5 minutes in order to keep it warm and to speed up initial SSR requests.
- A scheduled rule to trigger the cleanup Lambda function for deleting the outdated static assets of the Nuxt app from S3 every tuesday at 03:30 AM GMT.
- Athena: A database and table to analyze the access logs of the Nuxt app's CloudFront distribution. Only created if
enableAccessLogsAnalysis
is set totrue
.
Guidelines
In the following, you can find some guidelines for the deployment and usages of this package.
Automatically deploy on every push (CD) via GitHub Actions
Feel free to copy the following GitHub Actions YAML file content into a YAML file at .github/workflows/deploy.yml
to automatically build and deploy the Nuxt app to AWS on every push to a specific branch.This only works if you're using GitHub for the project's VCS repository.
name: Deploy
on:
push:
branches:
- master # Feel free to use another branch name
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4
# Enable if using Yarn >= 2
# - name: Enable Corepack for Yarn
# run: corepack enable
- name: Configure Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile # or `yarn install --immutable` for Yarn >= 2
- name: Build and deploy to AWS
run: node_modules/.bin/cdk-nuxt-deploy-server # Or run a customized deployment, see 'Build and Deploy' section
env:
# Create an IAM user on AWS for the deployment and create the appropriate secrets in the GitHub repository secrets
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}