Skip to content
This repository was archived by the owner on May 10, 2021. It is now read-only.

Commit 24d549f

Browse files
committed
Fix: Pre-rendered index.js page should not cause error
When we copy the pre-rendered pages to `out/`, we do a check to make sure that the file does not already exist. This is to make sure that we don't silently overwrite one of the files copied from `public/`, for example. But for `index.js` files, Netlify always creates two page entries, one routing to `/` and one routing to `/index`. So in this case, the first copying of `index.js` to `out/` goes fine. The second copying fails because `index.js` already exists. We fix this by first filtering our list of pages for unique pages and then performing the copy operation. Fixes: #2 (comment)
1 parent 683b656 commit 24d549f

File tree

5 files changed

+138
-2
lines changed

5 files changed

+138
-2
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,4 @@ next-on-netlify has only been tested on NextJS version 9 and above.
136136
🙌 Big "thank you" to the following people for their contributions:
137137
- [@spencewood](https://github.com/spencewood)
138138
- [@alxhghs](https://github.com/alxhghs)
139+
- [@gamliela](https://github.com/gamliela)

next-on-netlify.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ copySync(
6969

7070
// 2.3 SSR Setup: Copy SSR pages to functions/_next/pages
7171
// From there, they can be served by our nextRouter Netlify function.
72-
ssrPages.forEach(({ file }) => {
72+
73+
// Get unique set of JS files to copy. index.js might be present twice, for
74+
// example.
75+
const jsFilesToCopy = [...new Set(ssrPages.map(page => page.file))]
76+
77+
jsFilesToCopy.forEach(file => {
7378
console.log(` > ${file}`)
7479

7580
copySync(
@@ -114,7 +119,13 @@ if(existsSync(PUBLIC_PATH)) {
114119
// These are static, so they do not need to be handled by our nextRouter.
115120
console.log(`\x1b[1m🔥 Writing pre-rendered HTML pages to ${OUTPUT_PATH}\x1b[22m`)
116121

117-
htmlPages.forEach(({ file }) => {
122+
// Get unique set of html files to copy.
123+
// index.html might be present twice, for example. We need to filter one out,
124+
// otherwise our second attempt to copy the file would crash, since it already
125+
// exists.
126+
const htmlFilesToCopy = [...new Set(htmlPages.map(page => page.file))]
127+
128+
htmlFilesToCopy.forEach(file => {
118129
console.log(` > ${file}`)
119130

120131
// The path to the file, relative to the pages directory
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const PreRenderedPage = () => (
2+
<p>This page is pre-rendered.</p>
3+
)
4+
5+
export default PreRenderedPage
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const PreRenderedPage = () => (
2+
<p>This page is pre-rendered.</p>
3+
)
4+
5+
export default PreRenderedPage

tests/preRenderedIndexPages.test.js

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Test that next-on-netlify does not crash when pre-rendering index.js file.
2+
// See: https://github.com/FinnWoelm/next-on-netlify/issues/2#issuecomment-636415494
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-prerendered-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 30 seconds
51+
30 * 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("Preparing Netlify Function for SSR pages: functions/nextRouter")
64+
expect(BUILD_OUTPUT).toMatch("Writing pre-rendered HTML pages to out/")
65+
expect(BUILD_OUTPUT).toMatch("Copying static NextJS assets to out/")
66+
expect(BUILD_OUTPUT).toMatch("Setting up redirects")
67+
expect(BUILD_OUTPUT).toMatch("Success! All done!")
68+
})
69+
})
70+
71+
describe('Static Pages', () => {
72+
test('copies static pages to output directory', () => {
73+
const OUTPUT_PATH = join(PROJECT_PATH, "out")
74+
75+
expect(existsSync(join(OUTPUT_PATH, "index.html"))).toBe(true)
76+
expect(existsSync(join(OUTPUT_PATH, "shows.html"))).toBe(true)
77+
})
78+
79+
test('copies static assets to out/_next/ directory', () => {
80+
const dirs = readdirSync(join(PROJECT_PATH, "out", "_next", "static"))
81+
82+
expect(dirs.length).toBe(3)
83+
expect(dirs).toContain("chunks")
84+
expect(dirs).toContain("runtime")
85+
})
86+
})
87+
88+
describe('404 Page', () => {
89+
test('copies 404.html to output directory', () => {
90+
const OUTPUT_PATH = join(PROJECT_PATH, "out")
91+
92+
expect(existsSync(join(OUTPUT_PATH, "404.html"))).toBe(true)
93+
})
94+
95+
// This is required for 404.html to work on netlify-dev
96+
test('copies 404.html to directory root', () => {
97+
expect(existsSync(join(PROJECT_PATH, "404.html"))).toBe(true)
98+
})
99+
})
100+
101+
describe('Routing',() => {
102+
test('creates Netlify redirects', async () => {
103+
// Read _redirects file
104+
const contents = readFileSync(join(PROJECT_PATH, "out", "_redirects"))
105+
106+
// Convert contents into an array, each line being one element
107+
const redirects = contents.toString().split("\n")
108+
109+
// Check that routes are present
110+
expect(redirects).toContain("/ /index.html 200")
111+
expect(redirects).toContain("/index /index.html 200")
112+
expect(redirects).toContain("/shows /shows.html 200")
113+
})
114+
})

0 commit comments

Comments
 (0)