Skip to content

๐ŸŒ CDN Integration Guide (AWS S3 + CloudFront + Vite + Vercel) โ€‹

Goal: Serve static assets (images, CSS, JS, fonts, etc.) efficiently from AWS S3 + CloudFront while deploying your Vue 3 + Vite app via Vercel.

This setup ensures blazing-fast asset delivery, cache safety, easy rollbacks, and lightweight frontend deployments.


๐Ÿงฉ Project Overview โ€‹

This setup supports three distinct build modes:

Build TypeDescriptionUse Case
Local Build (npm run build)Normal Vite build, serves assets locally from /assets/.Local development.
Timestamped Build (npm run build:ts)Builds and uploads versioned assets (e.g., /assets/20251004175023/assets/).Local testing of CDN flow.
Production Build (via GitHub Actions)Builds timestamped assets, uploads to S3 + CloudFront, and deploys the app to Vercel.CI/CD deployment for production.

โš™๏ธ 1. Local Build Flow (npm run dev or npm run build) โ€‹

๐Ÿ”น Purpose โ€‹

For quick development and testing using your local server.

๐Ÿ”น Flow โ€‹

  1. The getAssets.js file dynamically imports all images (and subdirectories) from /src/assets/.
  2. The Vue app uses Vueโ€™s provide/inject API to make these images globally accessible.

Example:

js
// getAssets.js
const modules = import.meta.glob('./**/*.@(jpg|png|gif|svg)', { eager: true });
let images = {};

for (const path in modules) {
  const fileName = path.split('/').pop();
  images[fileName] = modules[path].default;
}

export default images;

App setup:

js
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import images from './assets/getAssets.js';

const app = createApp(App);
app.provide('appImages', images);
app.mount('#app');

In components:

vue
<img :src="appImages['logo.png']" alt="Logo" />

โœ… Assets are resolved from local /assets/ folder. โŒ No CDN or AWS involvement.


๐Ÿ•’ 2. Timestamped Build Flow (npm run build:ts) โ€‹

๐Ÿ”น Purpose โ€‹

To test the CDN flow locally, ensuring that assets are built, uploaded to S3, and linked correctly in the HTML.

๐Ÿ”น Key Behavior โ€‹

  • Generates a timestamp like 20251004175023

  • Builds your app using Vite with that timestamp

  • Uploads the built assets to:

    s3://test-cdn-pipeline/assets/<timestamp>/assets/
  • Rewrites asset URLs in index.html:

    https://d2ip2t1fu9lfn9.cloudfront.net/assets/<timestamp>/assets/<file>.js

๐Ÿ”น Environment Requirements โ€‹

You need a .env.production file locally:

env
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
VITE_CDN_URL=https://<your-cloudfront-domain>

๐Ÿ”น Commands โ€‹

bash
npm run build:ts

๐Ÿ”น Under the Hood โ€‹

build:ts triggers scripts/build-and-upload.js, which:

  1. Generates a timestamp.
  2. Runs vite build with that timestamp.
  3. Uploads the dist/assets folder to S3 under /assets/<timestamp>/assets/.

๐Ÿš€ 3. Production Build Flow (CI/CD) โ€‹

Triggered automatically on push to main branch via GitHub Actions.

๐Ÿ”น Pipeline Overview โ€‹

  1. build.yml โ€” Builds app and sets BUILD_TIMESTAMP.

  2. upload-assets.yml โ€” Uploads assets to:

    • /assets/<timestamp>/assets/ (versioned)
    • /assets/latest/ (for production)
    • Invalidates CloudFront cache.
  3. deploy-vercel.yml โ€” Deploys the latest dist folder to Vercel.

๐Ÿ”น GitHub Secrets Required โ€‹

Secret NameDescription
AWS_ACCESS_KEY_IDIAM access key with S3 + CloudFront permissions.
AWS_SECRET_ACCESS_KEYSecret key for the above.
AWS_REGIONYour AWS region (e.g., eu-north-1).
CLOUDFRONT_DIST_IDYour CloudFront distribution ID.
VERCEL_TOKENVercel personal access token.
VERCEL_PROJECT_IDVercel project ID.
VERCEL_ORG_IDVercel organization ID.
VITE_CDN_URLCloudFront URL (e.g., https://dxxxxx.cloudfront.net).

๐Ÿง 4. AWS Setup Guide โ€‹

๐Ÿชณ S3 Bucket Setup โ€‹

  1. Create an S3 bucket (e.g., test-cdn-pipeline).
  2. Disable โ€œBlock all public access.โ€
  3. Enable versioning if you want historical rollbacks.
  4. Add this bucket policy (replace with your CloudFront distribution ID):
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipal",
      "Effect": "Allow",
      "Principal": { "Service": "cloudfront.amazonaws.com" },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::test-cdn-pipeline/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::<YOUR_AWS_ACCOUNT_ID>:distribution/<YOUR_DIST_ID>"
        }
      }
    }
  ]
}

๐ŸŒ CloudFront Setup โ€‹

  1. Origin Domain: your S3 bucket (e.g., test-cdn-pipeline.s3.eu-north-1.amazonaws.com)

  2. Origin Access Control (OAC):

    • Create a new OAC and attach it to your S3 bucket.
  3. Viewer Protocol Policy: Redirect HTTP โ†’ HTTPS

  4. Cache Policy: Managed-CachingOptimized

  5. Origin Request Policy: Managed-CORS-With-Preflight

  6. Response Header Policy: none (optional)


โณ Lifecycle Rules โ€‹

In your S3 bucket โ†’ Management โ†’ Lifecycle Rules, add:

  • Rule name: delete-old-asset-versions
  • Prefix: assets/
  • Action: Delete objects older than 1 day
  • Filter: Include all objects
  • Enabled: โœ… Yes

This keeps the bucket clean by auto-deleting old timestamped folders, leaving only recent ones.


๐Ÿ— File Reference Overview โ€‹

FilePurpose
vite.config.jsHandles asset URL rewriting to CDN.
scripts/deploy-cdn.jsUploads built files to S3 and rewrites HTML.
scripts/build-and-upload.jsGenerates timestamp, builds app, and calls deploy script.
.github/workflows/build.ymlAutomates full CI/CD build, upload, and deploy.
.github/workflows/upload-assets.ymlUploads assets and invalidates cache.
.github/workflows/deploy-vercel.ymlDeploys built app to Vercel.

๐Ÿง  Rollback Strategy โ€‹

Each build is stored under /assets/<timestamp>/assets/. To roll back:

  1. Find your previous timestamp folder in S3.

  2. Replace latest with that version manually:

    bash
    aws s3 sync s3://test-cdn-pipeline/assets/20251004175023/assets/ s3://test-cdn-pipeline/assets/latest/assets/ --delete
  3. Invalidate CloudFront cache.


๐Ÿ—ณ Summary โ€‹

FeatureLocalTimestampProduction
Assets Location/assets//assets/<timestamp>/assets//assets/latest/
CDN UsedโŒโœ…โœ…
Upload to S3โŒโœ…โœ…
CloudFront InvalidationโŒโŒโœ…
Auto CleanupโŒโœ… via Lifecycleโœ… via Lifecycle
DeploymentLocalLocal TestVercel CI/CD

๐Ÿงช Pro Tips โ€‹

  • Use timestamped builds for internal QA / preview environments.

  • Always keep the latest folder synced for production.

  • If a file gets 403 (Access Denied), double-check:

    • S3 policy matches CloudFront OAC ARN.
    • CloudFront cache is invalidated.
    • The bucket region and distribution are correctly configured.

โค๏ธ Credits โ€‹

Created for a scalable Vite + Vue + AWS + Vercel CDN pipeline by Altersquare