← Back
serverless

Single Page App deploy with fullstack-serverless

Project setup #

create-react-app spa-test
cd spa-test
rm src/*
touch src/index.js
# edit index.js file (see below)
yarn start
yarn build
yarn add --dev serverless fullstack-serverless
touch serverless.yml
# edit serverless.yml (see below)
# add AWS credentials (see below)
# add "deploy": "serverless deploy" to package.json scripts

src/index.js:

import React from "react";
import ReactDOM from "react-dom";

const App = () => (
<div>
<h1>Hello</h1>
<p>You are on {window.location.pathname}</p>
</div>
);

ReactDOM.render(<App />, document.getElementById("root"));

serverless.yml:

plugins:
- fullstack-serverless

service: spa-test

provider:
name: aws
runtime: nodejs6.10
#stage: dev # Set the default stage used. Default is dev
#region: us-east-1 # Overwrite the default region used. Default is us-east-1

custom:
fullstack:
domain:
certificate:
bucketName: deploy
distributionFolder: build # Path to the client assets to be uploaded to S3
indexDocument: index.html # The index document to use (not used in this config)
errorDocument: error.html # The error document to use (not used in this config)
singlePageApp: true # If true 403 errors will be rerouted (missing assets) to your root index document
apiPath: api # The path prefix for your API Gateway lambdas.
clientCommand: yarn build # Command to generate the client assets. Defaults to doing nothing
clientSrcPath: . # The path to where you want to run the clientCommand

~/.aws/credentials:

[default]
aws_access_key_id = ACCESS_KEY
aws_secret_access_key = SECRET_KEY

First deploy #

The first time, it takes more than 10 minutes

yarn deploy

Result:

Serverless: Packaging service...
Serverless: Removing logging bucket...
Serverless: Setting price class PriceClass_All...
Serverless: Setting ApiGateway stage to 'dev'...
Serverless: Setting API path prefix to 'api'...
Serverless: Configuring distribution for single page web app...
Serverless: Setting up 'spa-test-dev-deploy' bucket...
Serverless: Setting indexDocument to 'index.html'...
Serverless: Setting errorDocument to 'error.html'...
Serverless: ApiGatewayRestApi not found, removing orgin from CloudFront...
Serverless: Creating Stack...
....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Validating template...
Serverless: Updating Stack...
....
Serverless: Stack update finished...
Serverless: Generating client...
Serverless: Client generation process succeeded...
Serverless: This deployment will:
Serverless: - Remove all existing files from bucket 'spa-test-dev-deploy'
Serverless: - Upload all files from 'build' to bucket 'spa-test-dev-deploy'
Serverless: Looking for bucket 'spa-test-dev-deploy'...
Serverless: Bucket found...
Serverless: Deleting all objects from bucket...
Serverless: Uploading client files to bucket...
Serverless: Success! Client deployed.
Service Information
service: spa-test
stage: dev
region: us-east-1
stack: spa-test-dev
resources: 5
api keys:
  None
endpoints:
  None
functions:
  None
layers:
  None
CloudFront domain name
  d2fnezabgre4sw.cloudfront.net (CNAME: null)

https://console.aws.amazon.com/s3/buckets/spa-test-dev-deploy/?region=us-east-1&tab=overview

Configuring domain and https #

Setup DNS #

Depends on your DNS provider. Add a CNAME to the cloudfront domain name.

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html

Add the domain name to serverless.yml

Amazon Certificate Manager #

https://console.aws.amazon.com/acm/home?region=us-east-1#/

Add certificate to serverless.yml

More deploys #

Cloudfront cache are not invalidated when deploying, so I use this (package.json) scripts (that uses aws-cli):

"deploy": "serverless deploy -v && yarn run cloudfront:invalidate",
"cloudfront:invalidate": "aws cloudfront create-invalidation --distribution-id AWS_DIST_ID --paths '/*'",

Then yarn deploy

Resources #