Skip to content
This repository was archived by the owner on Jan 28, 2025. It is now read-only.

Commit a577721

Browse files
feat: add support for custom page routes
1 parent 2639b5d commit a577721

File tree

8 files changed

+124
-9
lines changed

8 files changed

+124
-9
lines changed

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ The plugin targets [Next 8 serverless mode](https://nextjs.org/blog/next-8/#serv
2020
- [Deploying](#deploying)
2121
- [Deploying a single page](#deploying-a-single-page)
2222
- [Overriding page configuration](#overriding-page-configuration)
23+
- [Custom page routing](#custom-page-routing)
2324
- [Examples](#examples)
2425

2526
## Motivation
@@ -154,6 +155,43 @@ The example above will deploy the `about` page function with a smaller `memorySi
154155

155156
You can set any function property described [here](https://serverless.com/framework/docs/providers/aws/guide/functions#configuration). The values provided will be merged onto the plugin defaults.
156157

158+
## Custom page routing
159+
160+
The default page route is `/{pageName}`. You may want to serve your page from a different path. This is possible by setting your own page http path in the `pageConfig`. For example for `pages/post.js`:
161+
162+
```js
163+
class Post extends React.Component {
164+
static async getInitialProps({ query }) {
165+
return {
166+
slug: query.slug
167+
};
168+
}
169+
render() {
170+
return <h1>Post page: {this.props.slug}</h1>;
171+
}
172+
}
173+
174+
export default Post;
175+
```
176+
177+
```yml
178+
plugins:
179+
- serverless-nextjs-plugin
180+
181+
custom:
182+
serverless-nextjs:
183+
nextConfigDir: ./
184+
pageConfig:
185+
post:
186+
events:
187+
- http:
188+
path: post/{slug}
189+
request:
190+
parameters:
191+
paths:
192+
slug: true
193+
```
194+
157195
## Examples
158196

159197
See the `examples/` directory.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Post extends React.Component {
2+
static async getInitialProps({ query }) {
3+
return {
4+
slug: query.slug
5+
};
6+
}
7+
render() {
8+
return <h1>Post page: {this.props.slug}</h1>;
9+
}
10+
}
11+
12+
export default Post;

examples/basic-next-serverless-app/serverless.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ plugins:
1414
custom:
1515
serverless-nextjs:
1616
nextConfigDir: ./
17+
pageConfig:
18+
post:
19+
events:
20+
- http:
21+
path: post/{slug}
22+
request:
23+
parameters:
24+
paths:
25+
slug: true
1726

1827
package:
1928
# exclude everything

integration/__tests__/local-deploy.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ describe("Local Deployment Tests (via serverless-offline)", () => {
3636
);
3737
});
3838

39-
it("should return the post page content using custom route with id", () => {
39+
it("should return the post page content using custom route with slug", () => {
4040
expect.assertions(2);
4141

42-
return httpGet("http://localhost:3000/posts/2").then(
42+
return httpGet("http://localhost:3000/post/hello").then(
4343
({ response, statusCode }) => {
4444
expect(statusCode).toBe(200);
45-
expect(response).toContain("Post page");
45+
expect(response).toContain("Post page: <!-- -->hello");
4646
}
4747
);
4848
});
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import React from "react";
22

3-
function Post() {
4-
return <div>Post page</div>;
3+
class Post extends React.Component {
4+
static async getInitialProps({ query }) {
5+
return {
6+
slug: query.slug
7+
};
8+
}
9+
render() {
10+
return <h1>Post page: {this.props.slug}</h1>;
11+
}
512
}
613

714
export default Post;

integration/app-with-serverless-offline/serverless.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ custom:
1515
post:
1616
events:
1717
- http:
18-
path: posts/{id}
18+
path: post/{slug}
1919
request:
2020
parameters:
2121
paths:
22-
id: true
22+
slug: true
2323

2424
package:
2525
# exclude everything

lib/__tests__/compatLayer.request.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,37 @@ describe("compatLayer.request", () => {
101101
);
102102
});
103103

104+
it('event pathParameters { foo: "bar", bar: "baz" }', () => {
105+
const { req } = create({
106+
requestContext: {
107+
path: "/"
108+
},
109+
pathParameters: {
110+
foo: "bar",
111+
bar: "baz"
112+
}
113+
});
114+
115+
expect(req.url).toEqual("/?foo=bar&bar=baz");
116+
});
117+
118+
it("event pathParameters and queryString", () => {
119+
const { req } = create({
120+
requestContext: {
121+
path: "/"
122+
},
123+
multiValueQueryStringParameters: {
124+
abc: "def"
125+
},
126+
pathParameters: {
127+
foo: "bar",
128+
bar: "baz"
129+
}
130+
});
131+
132+
expect(req.url).toEqual("/?abc=def&foo=bar&bar=baz");
133+
});
134+
104135
it("request method", () => {
105136
const { req } = create({
106137
requestContext: {

lib/compatLayer.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,28 @@ const reqResMapper = (event, callback) => {
1616
""
1717
);
1818

19+
let qs = "";
20+
1921
if (event.multiValueQueryStringParameters) {
20-
req.url +=
21-
"?" + queryString.stringify(event.multiValueQueryStringParameters);
22+
qs += queryString.stringify(event.multiValueQueryStringParameters);
23+
}
24+
25+
if (event.pathParameters) {
26+
const pathParametersQs = queryString.stringify(event.pathParameters);
27+
28+
if (qs.length > 0) {
29+
qs += `&${pathParametersQs}`;
30+
} else {
31+
qs += pathParametersQs;
32+
}
2233
}
34+
35+
const hasQueryString = qs.length > 0;
36+
37+
if (hasQueryString) {
38+
req.url += `?${qs}`;
39+
}
40+
2341
req.method = event.httpMethod;
2442
req.rawHeaders = [];
2543
req.headers = {};

0 commit comments

Comments
 (0)