2.3.1 • Published 3 months ago

cdk-nuxt v2.3.1

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

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 aws-cdk@2.128.0 --dev # CDK cli with this exact version for the deployment

Setup

  1. Set the Nitro preset on your Nuxt configuration file (nuxt.config.js) to aws-lambda:
    export default defineNuxtConfig({
        ...
        nitro: {
            preset: 'aws-lambda'
        },
        ...      
    });
    See https://nitro.unjs.io/deploy/providers/aws for more details.
  2. Remove "type": "module" from your package.json file, if it exists. This is required to make the CDK stack work. Click here for details.
  3. 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.
  4. 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.
  5. 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 displayed ARN for the certificate. You will need it in step 7.
  6. 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 displayed ARN 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.
  7. 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 props env.account (setup step 3), hostedZoneId (setup step 4), regionalTlsCertificateArn (setup step 5) and globalTlsCertificateArn (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 the stack/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.
  • 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 to true.
  • Route53: Two DNS records (A for IPv4 and AAAA 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 to true.

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 }}
2.3.0-8

3 months ago

2.3.0-5

3 months ago

2.3.0-4

3 months ago

2.3.0-6

3 months ago

2.3.0

3 months ago

2.3.1

3 months ago

2.3.0-3

3 months ago

2.3.0-1

3 months ago

2.3.0-0

3 months ago

2.3.0-2

3 months ago

1.0.1

10 months ago

1.0.0

10 months ago

1.2.3

8 months ago

2.2.0

5 months ago

0.11.0

10 months ago

0.13.0

10 months ago

0.13.1

10 months ago

2.0.1

6 months ago

2.0.0

7 months ago

1.1.0

8 months ago

1.3.1

8 months ago

1.3.0

8 months ago

0.10.1

10 months ago

0.12.0

10 months ago

0.10.2

10 months ago

0.12.1

10 months ago

0.10.3

10 months ago

0.14.0

10 months ago

0.12.2

10 months ago

0.10.4

10 months ago

2.1.0

6 months ago

0.10.0

10 months ago

0.9.0

1 year ago

0.8.1

1 year ago

0.8.0

1 year ago

0.7.0

2 years ago

0.4.5

2 years ago

0.6.2

2 years ago

0.4.4

2 years ago

0.4.7

2 years ago

0.4.6

2 years ago

0.5.0

2 years ago

0.6.1

2 years ago

0.4.3

2 years ago

0.6.0

2 years ago

0.5.1

2 years ago

0.3.12

2 years ago

0.4.1

2 years ago

0.4.0

2 years ago

0.4.2

2 years ago

0.3.11

2 years ago

0.3.10

2 years ago

0.3.9

2 years ago

0.3.8

2 years ago

0.3.7

2 years ago

0.3.6

2 years ago

0.3.5

2 years ago

0.3.4

2 years ago

0.3.3

2 years ago

0.3.2

2 years ago

0.3.1

2 years ago

0.3.0

2 years ago

0.2.11

2 years ago

0.2.10

2 years ago

0.2.9

2 years ago

0.2.8

2 years ago

0.2.7

2 years ago

0.2.6

2 years ago

0.2.5

2 years ago

0.2.4

2 years ago

0.2.3

2 years ago

0.2.2

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.1.1

2 years ago