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?
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.
Most helpful comment
Solution:
Using
/{any+}allows to catch all sub routes, no matter the depth.