Deploy to AWS Lambda?

Hey @sean, that is awesome!!

I did an experiment a while ago to embed the static files inside the server.js file, just to know if that is something we could do in the future: https://github.com/luisherranz/embed-files-in-node-server

But I really like your approach. I am not familiar with the Serverless framework to be honest but it looks really cool.

I guess the next step would be to add CloudFront in front of everything. Have you thought about that? Can it be done with the serverless.yaml file as well?

If so, maybe you can make everything immutable (cache for a year even the HTML) and use a plugin like C3 CloudFront Cache by @hideokamoto to invalidate the cache from your WordPress.

Let us know what you find out.

There’s an issue created (in the docs repository) to create a guide about this

2 Likes

Hey @luisherranz,

Yes, I have been able to cache everything behind CloudFront!

Here is my updated serverless.yml

service: example2020

excludeDevDependencies: true

plugins:
  - serverless-aws-static-file-handler
  - serverless-offline

custom:
  apiGateway:
    binaryMediaTypes:
      - "*/*"

provider:
  name: aws
  runtime: nodejs12.x

functions:
  app:
    handler: lambda.handler
    events:
      - http:
          path: /
          method: any
      - http:
          path: /{proxy+}
          method: any

  static:
    handler: lambda.static
    events:
      - http:
          path: /static/{proxy+}
          method: get

  favicon:
    handler: lambda.favicon
    events:
      - http:
          path: /favicon.ico
          method: get

resources:
  Resources:
    CloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Comment: Example Site
          Aliases:
            - example.com.au
          ViewerCertificate:
            AcmCertificateArn: arn:aws:acm:us-east-1:100000000000:certificate/some-certificate-slug
            SslSupportMethod: sni-only
          DefaultCacheBehavior:
            TargetOriginId: MyFirstOrigin
            ViewerProtocolPolicy: "redirect-to-https"
            Compress: true
            MinTTL: 31536000
            DefaultTTL: 31536000
            ForwardedValues:
              QueryString: false
          Enabled: true
          HttpVersion: http2
          Origins:
            - Id: MyFirstOrigin
              DomainName:
                Fn::Join:
                  - "."
                  - - Ref: ApiGatewayRestApi
                    - execute-api.us-east-1.amazonaws.com
              OriginPath: /dev
              CustomOriginConfig:
                HTTPPort: 80
                HTTPSPort: 443
                OriginProtocolPolicy: https-only

And I also has to modify my lambda.js file to handle setting a Cache-Control header on my static resources:

const awsServerlessExpress = require("aws-serverless-express");
const app = require("./build/server.js").default;
const server = awsServerlessExpress.createServer(app);
const path = require("path");
const FileHandler = require("serverless-aws-static-file-handler");

// Handle routing to Frontity Server
exports.handler = (event, context) => {
  awsServerlessExpress.proxy(server, event, context);
};

// Handle returning all static files located in `/build/static/`
const StaticFilesPath = path.join(__dirname, "./build/static/");
const staticFileHandler = new FileHandler(StaticFilesPath);
exports.static = async (event, context) => {
  if (!event.path.startsWith("/static/")) {
    throw new Error(`[404] Invalid filepath for this resource: ${fname}`);
  }
  let response = await staticFileHandler.get(event, context);
  response.headers = {
    'Content-Type': response.headers["Content-Type"],
    'Cache-Control': 'max-age=31536000',
 }
 return response;
};

// Handle returning `favicon.ico` file in the project root
const RootFilesPath = path.join(__dirname);
const rootFileHandler = new FileHandler(RootFilesPath);
exports.favicon = async (event, context) => {
  return rootFileHandler.get(event, context);
}

Hope this helps!

1 Like

That’s awesome :clap: :clap: Congratulations :slight_smile:

Are you caching the HTML requests as well?

I guess you could use a s-maxage=31536000 header to store the HTML in Cloudfront for as long as possible, and then clear the cache from WordPress each time you update/publish a post using this plugin: https://wordpress.org/plugins/c3-cloudfront-clear-cache/