aws-amplify / aws-amplify/amplify-hosting
Next.js SSR app 404s on SSG dynamic route with hyphen in filename
- Dominant language
- Dockerfile
- Stars
- 481
- Forks
- 123
- PR merge metrics
- No merged PRs in 30d
Description
### Before opening, please confirm:
- [X] I have checked to see if my question is addressed in the [FAQ](https://github.com/aws-amplify/amplify-console/blob/master/FAQ.md).
- [X] I have [searched for duplicate or closed issues](https://github.com/aws-amplify/amplify-console/issues?q=is%3Aissue+).
- [X] I have read the guide for [submitting bug reports](https://github.com/aws-amplify/amplify-console/blob/master/CONTRIBUTING.md).
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
### App Id
dc3blsn6e63vx
### Region
us-east-1
### Amplify Console feature
Not applicable
### Describe the bug
When visiting the following URL: https://trying-to-reproduce-ssr-issue.dc3blsn6e63vx.amplifyapp.com/with-named/a, you will get a `404`. The filename for the dynamic route (at the `a`) has a hyphen in it: `a-a.tsx`. When the same file is available but it does not have a hyphen in the name: https://trying-to-reproduce-ssr-issue.dc3blsn6e63vx.amplifyapp.com/with-indexes/static/c, the page loads successfully.
### Expected behavior
Hyphens in dynamic route filenames do not automatically result in a `404`.
### Reproduction steps
1. Create a Next.js SSR project
2. Add a SSG/static dynamic route with a hyphen in the name `[a-a].jsx`
3. Perform a GET to that route -> 404
### Build Settings
```yaml
version: 1
frontend:
phases:
preBuild:
commands:
- yarn install
build:
commands:
- yarn build
artifacts:
baseDirectory: .next
files:
- "**/*"
cache:
paths:
- node_modules/**/*
```
### Additional information
Not sure if this is useful, but here is the `routes-manifest.js` that gets created within Lambda
```json
{
"version":3,
"pages404":true,
"basePath":"",
"redirects":[
],
"headers":[
],
"dynamicRoutes":[
{
"page":"/with-indexes/static/[c]",
"regex":"^/with\\-indexes/static/([^/]+?)(?:/)?$",
"routeKeys":{
"c":"c"
},
"namedRegex":"^/with\\-indexes/static/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/static/[c]/static",
"regex":"^/with\\-indexes/static/([^/]+?)/static(?:/)?$",
"routeKeys":{
"c":"c"
},
"namedRegex":"^/with\\-indexes/static/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-indexes/static/[c]/[d]",
"regex":"^/with\\-indexes/static/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"c":"c",
"d":"d"
},
"namedRegex":"^/with\\-indexes/static/(?[^/]+?)/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/[a]",
"regex":"^/with\\-indexes/([^/]+?)(?:/)?$",
"routeKeys":{
"a":"a"
},
"namedRegex":"^/with\\-indexes/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/[a]/static",
"regex":"^/with\\-indexes/([^/]+?)/static(?:/)?$",
"routeKeys":{
"a":"a"
},
"namedRegex":"^/with\\-indexes/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-indexes/[a]/[b]",
"regex":"^/with\\-indexes/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"a":"a",
"b":"b"
},
"namedRegex":"^/with\\-indexes/(?[^/]+?)/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/[a]/[b]/static",
"regex":"^/with\\-indexes/([^/]+?)/([^/]+?)/static(?:/)?$",
"routeKeys":{
"a":"a",
"b":"b"
},
"namedRegex":"^/with\\-indexes/(?[^/]+?)/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-named/static/[c-c]",
"regex":"^/with\\-named/static/([^/]+?)(?:/)?$",
"routeKeys":{
"cc":"c-c"
},
"namedRegex":"^/with\\-named/static/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-named/static/[c-c]/static",
"regex":"^/with\\-named/static/([^/]+?)/static(?:/)?$",
"routeKeys":{
"cc":"c-c"
},
"namedRegex":"^/with\\-named/static/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-named/static/[c-c]/[d-d]",
"regex":"^/with\\-named/static/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"cc":"c-c",
"dd":"d-d"
},
"namedRegex":"^/with\\-named/static/(?[^/]+?)/(?
},
{
"page":"/with-named/[a-a]",
"regex":"^/with\\-named/([^/]+?)(?:/)?$",
"routeKeys":{
"aa":"a-a"
},
"namedRegex":"^/with\\-named/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-named/[a-a]/static",
"regex":"^/with\\-named/([^/]+?)/static(?:/)?$",
"routeKeys":{
"aa":"a-a"
},
"namedRegex":"^/with\\-named/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-named/[a-a]/[b-b]",
"regex":"^/with\\-named/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"aa":"a-a",
"bb":"b-b"
},
"namedRegex":"^/with\\-named/(?[^/]+?)/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-named/[a-a]/[b-b]/static",
"regex":"^/with\\-named/([^/]+?)/([^/]+?)/static(?:/)?$",
"routeKeys":{
"aa":"a-a",
"bb":"b-b"
},
"namedRegex":"^/with\\-named/(?[^/]+?)/(?[^/]+?)/static(?:/)?$"
}
],
"dataRoutes":[
],
"rewrites":[
]
}
```
Contributor guide
Research direction
Start by reproducing the issue with the `[a-a].jsx` SSG route and inspect the generated `routes-manifest.js` in Lambda, comparing it with the working `[c]` route. Done means a GET to `/with-named/a` succeeds when the dynamic route filename contains a hyphen, without regressing the working route.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, next.js
- Domain
- cloud, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100