Serverless-express: How to handle all routes?

Created on 1 Mar 2018  路  3Comments  路  Source: vendia/serverless-express

I am trying to build an app using Next.js and Serverless. Next is basically a SSR node server + react, and I want my "Next" app to handle all routes.

I successfully made it so it handles the main route (/) but still failing with the other routes.

import next from 'next';
import es from 'aws-serverless-express';

import { failure } from "../utils/browserResponse";
import { isHostedOnAWS } from "../utils/aws";

// XXX next.dev enabled HMR, which we don't want if not in development mode, or when we are on AWS's infrastructure
const app = next({ dev: !isHostedOnAWS() && process.env.NODE_ENV === 'development' });
const handle = app.getRequestHandler();
const server = es.createServer(handle);

export async function handler(event, context, callback) {
  try {
    return es.proxy(server, event, context);
  } catch (e) {
    callback(null, await failure({ status: false }, e));
  }
}

Here is my yml SLS config:

service:
  name: serverless-with-next

frameworkVersion: "1.26.1"

plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-plugin-simulate
  - serverless-jest-plugin
  - serverless-domain-manager

# Enable auto-packing of external modules
# See https://serverless-stack.com/chapters/add-support-for-es6-es7-javascript.html
custom:
  webpackIncludeModules: true
#  webpackIncludeModules:
#    forceInclude:
#      - next
  domains:
    development: 'swn.dev.vadorequest.fr'
  memorySizes: # TODO Check how much is actually needed
    development: 512
  customDomain:
    domainName: ${self:custom.domains.${self:provider.stage}}
#    basePath: '' # This will be prefixed to all routes
    stage: ${self:provider.stage}
    createRoute53Record: true
  simulate:
    dist: docker
#    services:
#      file: docker-compose.yml
#      projectName: serverless-with-next

# The `provider` block defines where your service will be deployed
provider:
  name: aws
  runtime: nodejs6.10
  timeout: 30
  stage: ${opt:stage, 'development'}
  region: ${opt:region, 'us-east-1'}
  memorySize: ${self:custom.memorySizes.${self:provider.stage}}
  environment:
    NODE_ENV: ${self:provider.stage}


package:
  individually: true

# The `functions` block defines what code to deploy
functions:
  server:
    handler: lambdas/server.handler
    events:
      - http:
          method: GET
          path: /
      - http:
          method: GET
          path: /_next/{proxy+}

  status:
    handler: lambdas/status/status.handler
    events:
      - http:
          method: get
          path: status

Any idea?


Repo: https://github.com/Vadorequest/serverless-with-next

Most helpful comment

Solution:

functions:
  server:
    handler: src/functions/server/server.handler
    events:
      - http:
          method: GET
          path: /
      - http:
          method: GET
          path: /static/{any+}
      - http:
          method: GET
          path: /_next/{proxy+} # Catch Next specific routes
      - http:
          method: GET
          path: /{any+} # Catch all unknown routes and redirect to main handler

Using /{any+} allows to catch all sub routes, no matter the depth.

All 3 comments

Solution:

functions:
  server:
    handler: src/functions/server/server.handler
    events:
      - http:
          method: GET
          path: /
      - http:
          method: GET
          path: /static/{any+}
      - http:
          method: GET
          path: /_next/{proxy+} # Catch Next specific routes
      - http:
          method: GET
          path: /{any+} # Catch all unknown routes and redirect to main handler

Using /{any+} allows to catch all sub routes, no matter the depth.

@Vadorequest thank you for sharing this - solves the exact question i was having.

Just for context: it seems like the /static/ and /_next/ paths

      - http:
          method: GET
          path: /static/{any+}
      - http:
          method: GET
          path: /_next/{proxy+} # Catch Next specific routes

would get picked up by the catch all path

      - http:
          method: GET
          path: /{any+} # Catch all unknown routes and redirect to main handler

Is there a reason that you defined those two explicitly?

I think I did it explicitly for the sake of readability, I may also have done some additional stuff for those routes (static, _next) which I removed when pasting my solution because it was unrelated.

Long story short, it should behave exactly the same.

Was this page helpful?
0 / 5 - 0 ratings