Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on May 10, 2021. It is now read-only.

Commit 5f2134f

Browse filesBrowse files
committed
Allow the main index route to be ssg rendered with getStaticProps
Previously, the / route having associated data would cause the build to fail as it would attempt to reference an /.html file instead of /index.html This also fixes a stability issue with the snapshot test for _redirects, which are not necessarily generated in a stable order.
1 parent 9bf3e9f commit 5f2134f
Copy full SHA for 5f2134f

File tree

Expand file treeCollapse file tree

9 files changed

+188
-20
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+188
-20
lines changed

‎lib/allNextJsPages.js

Copy file name to clipboardExpand all lines: lib/allNextJsPages.js
+15-2Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ const getAllPages = () => {
3434
return
3535

3636
// Skip page if it is actually an SSG page
37-
if(route in staticSsgPages || route in dynamicSsgPages)
37+
const normalizedRoute = route === "/index" ? "/" : route
38+
if(normalizedRoute in staticSsgPages || normalizedRoute in dynamicSsgPages)
3839
return
3940

4041
// Check if we already have a page pointing to this file
@@ -62,7 +63,7 @@ const getAllPages = () => {
6263

6364
// Parse SSG pages
6465
Object.entries(staticSsgPages).forEach(([ route, { dataRoute }]) => {
65-
pages.push(new Page({ route, type: "ssg", dataRoute }))
66+
pages.push(new Page({ route, type: "ssg", dataRoute, alternativeRoutes: route === "/" ? ["/index"] : [] }))
6667
})
6768
Object.entries(dynamicSsgPages).forEach(([ route, { dataRoute, fallback }]) => {
6869
// Ignore pages without fallback, these are already handled by the
@@ -100,6 +101,18 @@ class Page {
100101
return this.type === "ssg-fallback"
101102
}
102103

104+
routeFile(ext) {
105+
return `${this.route.replace(/^\/$/, '/index')}${ext}`
106+
}
107+
108+
get htmlFile() {
109+
return this.routeFile(".html")
110+
}
111+
112+
get jsonFile() {
113+
return this.routeFile(".json")
114+
}
115+
103116
// Return route and alternative routes as array
104117
get routesAsArray() {
105118
return [this.route, ...this.alternativeRoutes]

‎lib/setupRedirects.js

Copy file name to clipboardExpand all lines: lib/setupRedirects.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const setupRedirects = () => {
4242
}
4343
// SSG pages
4444
else if (page.isSsg()) {
45-
to = `${page.route}.html`
45+
to = page.htmlFile
4646
}
4747
// SSG fallback pages (for non pre-rendered paths)
4848
else if (page.isSsgFallback()) {

‎lib/setupSsgPages.js

Copy file name to clipboardExpand all lines: lib/setupSsgPages.js
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ const setupSsgPages = () => {
1818
// Copy pre-rendered SSG pages to Netlify publish folder
1919
console.log(" ", "1. Copying pre-rendered SSG pages to", NETLIFY_PUBLISH_PATH)
2020

21-
ssgPages.forEach(({ route }) => {
22-
const filePath = join("pages", `${route}.html`)
21+
ssgPages.forEach(({ htmlFile }) => {
22+
const filePath = join("pages", htmlFile)
2323
console.log(" ", " ", filePath)
2424

2525
copySync(
2626
join(NEXT_DIST_DIR, "serverless", filePath),
27-
join(NETLIFY_PUBLISH_PATH, `${route}.html`),
27+
join(NETLIFY_PUBLISH_PATH, htmlFile),
2828
{
2929
overwrite: false,
3030
errorOnExist: true
@@ -36,8 +36,8 @@ const setupSsgPages = () => {
3636
const nextDataFolder = join(NETLIFY_PUBLISH_PATH, "_next", "data/")
3737
console.log(" ", "2. Copying SSG page data to", nextDataFolder)
3838

39-
ssgPages.forEach(({ route, dataRoute }) => {
40-
const dataPath = join("pages", `${route}.json`)
39+
ssgPages.forEach(({ jsonFile, dataRoute }) => {
40+
const dataPath = join("pages", jsonFile)
4141
console.log(" ", " ", dataPath)
4242

4343
copySync(

‎package-lock.json

Copy file name to clipboardExpand all lines: package-lock.json
+1-1Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tests/__snapshots__/defaults.test.js.snap

Copy file name to clipboardExpand all lines: tests/__snapshots__/defaults.test.js.snap
+11-11Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@
22

33
exports[`Routing creates Netlify redirects 1`] = `
44
"# Next-on-Netlify Redirects
5-
/api/static /.netlify/functions/next_api_static 200
6-
/getServerSideProps/static /.netlify/functions/next_getServerSideProps_static 200
7-
/_next/data/%BUILD_ID%/getServerSideProps/static.json /.netlify/functions/next_getServerSideProps_static 200
8-
/index /.netlify/functions/next_index 200
95
/ /.netlify/functions/next_index 200
10-
/static /static.html 200
116
/404 /404.html 200
7+
/_next/data/%BUILD_ID%/getServerSideProps/:id.json /.netlify/functions/next_getServerSideProps_id 200
8+
/_next/data/%BUILD_ID%/getServerSideProps/static.json /.netlify/functions/next_getServerSideProps_static 200
9+
/_next/data/%BUILD_ID%/getStaticProps/withFallback/:id.json /.netlify/functions/next_getStaticProps_withFallback_id 200
10+
/api/shows/* /.netlify/functions/next_api_shows_params 200
11+
/api/shows/:id /.netlify/functions/next_api_shows_id 200
12+
/api/static /.netlify/functions/next_api_static 200
13+
/getServerSideProps/:id /.netlify/functions/next_getServerSideProps_id 200
14+
/getServerSideProps/static /.netlify/functions/next_getServerSideProps_static 200
1215
/getStaticProps/1 /getStaticProps/1.html 200
1316
/getStaticProps/2 /getStaticProps/2.html 200
1417
/getStaticProps/static /getStaticProps/static.html 200
1518
/getStaticProps/withFallback/3 /getStaticProps/withFallback/3.html 200
1619
/getStaticProps/withFallback/4 /getStaticProps/withFallback/4.html 200
17-
/api/shows/:id /.netlify/functions/next_api_shows_id 200
18-
/api/shows/* /.netlify/functions/next_api_shows_params 200
19-
/getServerSideProps/:id /.netlify/functions/next_getServerSideProps_id 200
20-
/_next/data/%BUILD_ID%/getServerSideProps/:id.json /.netlify/functions/next_getServerSideProps_id 200
2120
/getStaticProps/withFallback/:id /.netlify/functions/next_getStaticProps_withFallback_id 200
22-
/_next/data/%BUILD_ID%/getStaticProps/withFallback/:id.json /.netlify/functions/next_getStaticProps_withFallback_id 200
23-
/shows/:id /.netlify/functions/next_shows_id 200
21+
/index /.netlify/functions/next_index 200
2422
/shows/* /.netlify/functions/next_shows_params 200
23+
/shows/:id /.netlify/functions/next_shows_id 200
24+
/static /static.html 200
2525
/static/:id /static/[id].html 200"
2626
`;

‎tests/defaults.test.js

Copy file name to clipboardExpand all lines: tests/defaults.test.js
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ describe('Routing',() => {
172172
// Replace non-persistent build ID with placeholder
173173
redirects = redirects.replace(/\/_next\/data\/[^\/]+\//g, "/_next/data/%BUILD_ID%/")
174174

175+
// Sort contents for a stable comparison
176+
redirects = redirects.split(/\n/).sort().join("\n")
177+
175178
// Check that redirects match
176179
expect(redirects).toMatchSnapshot()
177180
})
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Link from 'next/link'
2+
3+
const Page = ({ now }) => (
4+
<div>
5+
<h1>Date.now(): {now}</h1>
6+
7+
<Link href="/static">
8+
<a>Static page</a>
9+
</Link>
10+
</div>
11+
)
12+
13+
export async function getStaticProps(context) {
14+
return {
15+
props: {
16+
now: Date.now()
17+
}
18+
}
19+
}
20+
21+
export default Page
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Link from 'next/link'
2+
3+
const Page = ({ now }) => (
4+
<div>
5+
<h1>Date.now(): {now}</h1>
6+
7+
<Link href="/">
8+
<a>Index page</a>
9+
</Link>
10+
</div>
11+
)
12+
13+
export async function getStaticProps(context) {
14+
return {
15+
props: {
16+
now: Date.now()
17+
}
18+
}
19+
}
20+
21+
export default Page

‎tests/staticIndexPages.test.js

Copy file name to clipboard
+110Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Test that next-on-netlify does not crash when pre-rendering index.js file
2+
// with getStaticProps.
3+
4+
const { parse, join } = require('path')
5+
const { copySync, emptyDirSync, existsSync,
6+
readdirSync, readFileSync, readJsonSync } = require('fs-extra')
7+
const npmRunBuild = require("./helpers/npmRunBuild")
8+
9+
// The name of this test file (without extension)
10+
const FILENAME = parse(__filename).name
11+
12+
// The directory which will be used for testing.
13+
// We simulate a NextJS app within that directory, with pages, and a
14+
// package.json file.
15+
const PROJECT_PATH = join(__dirname, "builds", FILENAME)
16+
17+
// The directory that contains the fixtures, such as NextJS pages,
18+
// NextJS config, and package.json
19+
const FIXTURE_PATH = join(__dirname, "fixtures")
20+
21+
// Capture the output of `npm run build` to verify successful build
22+
let BUILD_OUTPUT
23+
24+
beforeAll(
25+
async () => {
26+
// Clear project directory
27+
emptyDirSync(PROJECT_PATH)
28+
emptyDirSync(join(PROJECT_PATH, "pages"))
29+
30+
// Copy NextJS pages and config
31+
copySync(
32+
join(FIXTURE_PATH, "pages-with-static-props-index"),
33+
join(PROJECT_PATH, "pages")
34+
)
35+
copySync(
36+
join(FIXTURE_PATH, "next.config.js"),
37+
join(PROJECT_PATH, "next.config.js")
38+
)
39+
40+
// Copy package.json
41+
copySync(
42+
join(FIXTURE_PATH, "package.json"),
43+
join(PROJECT_PATH, "package.json")
44+
)
45+
46+
// Invoke `npm run build`: Build Next and run next-on-netlify
47+
const { stdout } = await npmRunBuild({ directory: PROJECT_PATH })
48+
BUILD_OUTPUT = stdout
49+
},
50+
// time out after 180 seconds
51+
180 * 1000
52+
)
53+
54+
describe('Next', () => {
55+
test('builds successfully', () => {
56+
// NextJS output
57+
expect(BUILD_OUTPUT).toMatch("Creating an optimized production build...")
58+
expect(BUILD_OUTPUT).toMatch("Automatically optimizing pages...")
59+
expect(BUILD_OUTPUT).toMatch("First Load JS shared by all")
60+
61+
// Next on Netlify output
62+
expect(BUILD_OUTPUT).toMatch("Next on Netlify")
63+
expect(BUILD_OUTPUT).toMatch("Success! All done!")
64+
})
65+
})
66+
67+
describe('Static Pages', () => {
68+
test('copies static pages to output directory', () => {
69+
const OUTPUT_PATH = join(PROJECT_PATH, "out_publish")
70+
71+
expect(existsSync(join(OUTPUT_PATH, "index.html"))).toBe(true)
72+
expect(existsSync(join(OUTPUT_PATH, "static.html"))).toBe(true)
73+
})
74+
75+
test('copies static assets to out_publish/_next/ directory', () => {
76+
const dirs = readdirSync(join(PROJECT_PATH, "out_publish", "_next", "static"))
77+
78+
expect(dirs.length).toBe(3)
79+
expect(dirs).toContain("chunks")
80+
expect(dirs).toContain("runtime")
81+
})
82+
})
83+
84+
describe('404 Page', () => {
85+
test('copies 404.html to output directory', () => {
86+
const OUTPUT_PATH = join(PROJECT_PATH, "out_publish")
87+
88+
expect(existsSync(join(OUTPUT_PATH, "404.html"))).toBe(true)
89+
})
90+
91+
// This is required for 404.html to work on netlify-dev
92+
test('copies 404.html to directory root', () => {
93+
expect(existsSync(join(PROJECT_PATH, "404.html"))).toBe(true)
94+
})
95+
})
96+
97+
describe('Routing',() => {
98+
test('creates Netlify redirects', async () => {
99+
// Read _redirects file
100+
const contents = readFileSync(join(PROJECT_PATH, "out_publish", "_redirects"))
101+
102+
// Convert contents into an array, each line being one element
103+
const redirects = contents.toString().split("\n")
104+
105+
// Check that routes are present
106+
expect(redirects).toContain("/ /index.html 200")
107+
expect(redirects).toContain("/index /index.html 200")
108+
expect(redirects).toContain("/static /static.html 200")
109+
})
110+
})

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.