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

Commit 5b7d20d

Browse files
committed
Write HTML pages to out/ instead of public/
Rather than polluting the public/ directory (and potentially overwriting files), build HTML and static files to the out/ folder. Files and folders inside public/ are copied to out/. The out/ folder is consistent with the folder created by next export.
1 parent a71396d commit 5b7d20d

File tree

6 files changed

+80
-48
lines changed

6 files changed

+80
-48
lines changed

README.md

+4-7
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ We're almost done! We just have to tell Netlify how to build our NextJS app, whe
6363
[build]
6464
command = "npm run build"
6565
functions = "functions"
66-
publish = "public"
66+
publish = "out"
6767
```
6868

6969
We're done. Let's deploy 🚀🚀🚀
@@ -92,7 +92,7 @@ Then, add the following `[dev]` block to your `netlify.toml`:
9292

9393
[dev]
9494
functions = "functions"
95-
publish = "public"
95+
publish = "out"
9696
# We manually set the framework to static, otherwise Netlify automatically
9797
# detects NextJS and redirects do not work.
9898
# Read more: https://github.com/netlify/cli/blob/master/docs/netlify-dev.md#project-detection
@@ -106,8 +106,7 @@ Lastly, add the following lines to your `.gitignore`:
106106

107107
# Files generated by next-on-netlify command
108108
functions/nextRouter
109-
public/_next
110-
public/_redirects
109+
out/
111110
```
112111

113112
Now you're all set.
@@ -118,9 +117,7 @@ From now on, whenever you want to preview your application locally, just run:
118117

119118
#### Add Custom Redirects
120119

121-
next-on-netlify defines redirects in `public/_redirects`. Do not manually add redirects there or they will be overwritten the next time you run `next-on-netlify`.
122-
123-
Instead, you can define redirects in a `_redirects` file at the root level. These will be merged into the `public/_redirects` when you run `next-on-netlify`.
120+
You can define custom redirects in a `_redirects` file in the `public/` folder. When you run `next-on-netlify`, your redirects will be merged with the redirects defined by `next-on-netlify`. Note that your redirects take priority.
124121

125122
Or you can define custom redirects in the `netlify.toml` file.
126123

cypress/fixtures/netlify.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[build]
22
command = "npm run build"
33
functions = "functions"
4-
publish = "public"
4+
publish = "out"
55

66
[dev]
77
# We manually set the framework to static, otherwise Netlify automatically
88
# detects NextJS and redirects do not work.
99
# Read more: https://github.com/netlify/cli/blob/master/docs/netlify-dev.md#project-detection
1010
framework = "#static"
1111
functions = "functions"
12-
publish = "public"
12+
publish = "out"

next-on-netlify.js

+41-21
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const { copySync, emptyDirSync,
44
existsSync, readFileSync,
55
writeFileSync, writeJsonSync } = require('fs-extra')
6-
const { join } = require('path')
6+
const { join, relative } = require('path')
77
const collectNextjsPages = require('./lib/collectNextjsPages')
88
const getNextDistDir = require('./lib/getNextDistDir')
99

@@ -13,11 +13,15 @@ const NEXT_CONFIG_PATH = join(".", "next.config.js")
1313
// Path to the folder that NextJS builds to
1414
const NEXT_DIST_DIR = getNextDistDir({ nextConfigPath: NEXT_CONFIG_PATH })
1515
// Path to Netlify functions folder
16-
const FUNCTIONS_PATH = join(".", "functions")
16+
const FUNCTIONS_PATH = join(".", "functions/")
17+
// Path to output folder (same as `next export`)
18+
// This is where next-on-netlify will place all static files.
19+
// The publish key in netlify.toml should point to this folder.
20+
const OUTPUT_PATH = join(".", "out/")
1721
// Path to public folder
18-
const PUBLIC_PATH = join(".", "public")
22+
const PUBLIC_PATH = join(".", "public/")
1923
// Path to user-defined redirects
20-
const USER_REDIRECTS_PATH = join(".", "_redirects")
24+
const USER_REDIRECTS_PATH = join(PUBLIC_PATH, "_redirects")
2125
// Path to the router template
2226
const ROUTER_TEMPLATE_PATH = join(__dirname, "lib", "routerTemplate.js")
2327

@@ -91,38 +95,54 @@ writeFileSync(
9195

9296
// 3. HTML Setup
9397

94-
// 3.1 HTML Setup: Clean existing _next folder
95-
emptyDirSync(
96-
join(PUBLIC_PATH, "_next")
97-
)
98+
// 3.1 HTML Setup: Clean existing output folder
99+
emptyDirSync(OUTPUT_PATH)
100+
101+
// 3.2 HTML Setup: Copy files from public folder to output path
102+
if(existsSync(PUBLIC_PATH))
103+
copySync(PUBLIC_PATH, OUTPUT_PATH)
98104

99-
// 3.2 HTML Setup: Copy HTML pages to public/_next/pages
105+
// 3.3 HTML Setup: Copy HTML pages to the output folder
100106
// These are static, so they do not need to be handled by our nextRouter.
101-
htmlPages.forEach(({ file }) => (
107+
htmlPages.forEach(({ file }) => {
108+
// The path to the file, relative to the pages directory
109+
const relativePath = relative("pages", file)
110+
102111
copySync(
103-
join(NEXT_DIST_DIR, "serverless", file),
104-
join(PUBLIC_PATH, "_next", file)
112+
join(NEXT_DIST_DIR, "serverless", "pages",relativePath),
113+
join(OUTPUT_PATH, relativePath),
114+
{
115+
overwrite: false,
116+
errorOnExist: true
117+
}
105118
)
106-
))
119+
})
107120

108121

109122
// 4. Prepare NextJS static assets
110-
// Copy the NextJS' static assets from /.next/static to /public/_next/static.
123+
// Copy the NextJS' static assets from /.next/static to /out/_next/static.
111124
// These need to be available for NextJS to work.
112125
copySync(
113126
join(NEXT_DIST_DIR, "static"),
114-
join(PUBLIC_PATH, "_next", "static")
127+
join(OUTPUT_PATH, "_next", "static"),
128+
{
129+
overwrite: false,
130+
errorOnExist: true
131+
}
115132
)
116133

117134

118135
// 5. Generate the _redirects file
119136
// These redirects route all requests to the appropriate location: Either the
120137
// nextRouter Netlify function or one of our static HTML pages. They are merged
121-
// with the _redirects file at the root level, so you can still define your
122-
// custom redirects.
123-
const htmlRedirects = htmlPages.map(({ route, file }) => (
124-
`${route} /_next/${file} 200`
125-
))
138+
// with the _redirects file from the public/ folder, so you can still define
139+
// your custom redirects.
140+
const htmlRedirects = htmlPages.map(({ route, file }) => {
141+
// The path to the file, relative to the pages directory
142+
const relativePath = relative("pages", file)
143+
144+
return `${route} /${relativePath} 200`
145+
})
126146
const ssrRedirects = ssrPages.map(({ route }) => (
127147
`${route} /.netlify/functions/${ROUTER_FUNCTION_NAME} 200`
128148
))
@@ -135,7 +155,7 @@ if(existsSync(USER_REDIRECTS_PATH)) {
135155
}
136156

137157
writeFileSync(
138-
join(PUBLIC_PATH, "_redirects"),
158+
join(OUTPUT_PATH, "_redirects"),
139159
userRedirects + "\n\n" +
140160
"# Next-on-Netlify Redirects" + "\n" +
141161
nextjsRedirects

tests/customNextDistDir.test.js

+10-9
Original file line numberDiff line numberDiff line change
@@ -154,33 +154,34 @@ describe('API Pages', () => {
154154
})
155155

156156
describe('Static Pages', () => {
157-
test('copies static pages to public/_next/ directory', () => {
158-
const pages = join(PROJECT_PATH, "public", "_next", "pages")
157+
test('copies static pages to output directory', () => {
158+
const OUTPUT_PATH = join(PROJECT_PATH, "out")
159159

160-
expect(existsSync(join(pages, "static.html"))).toBe(true)
161-
expect(existsSync(join(pages, "static/[id].html"))).toBe(true)
160+
expect(existsSync(join(OUTPUT_PATH, "static.html"))).toBe(true)
161+
expect(existsSync(join(OUTPUT_PATH, "static/[id].html"))).toBe(true)
162162
})
163163

164-
test('copies static assets to public/_next/ directory', () => {
165-
const dirs = readdirSync(join(PROJECT_PATH, "public", "_next", "static"))
164+
test('copies static assets to out/_next/ directory', () => {
165+
const dirs = readdirSync(join(PROJECT_PATH, "out", "_next", "static"))
166166

167167
expect(dirs.length).toBe(3)
168168
expect(dirs).toContain("chunks")
169169
expect(dirs).toContain("runtime")
170170
})
171171
})
172172

173+
173174
describe('Routing',() => {
174175
test('creates Netlify redirects', async () => {
175176
// Read _redirects file
176-
const contents = readFileSync(join(PROJECT_PATH, "public", "_redirects"))
177+
const contents = readFileSync(join(PROJECT_PATH, "out", "_redirects"))
177178

178179
// Convert contents into an array, each line being one element
179180
const redirects = contents.toString().split("\n")
180181

181182
// Check that routes are present
182-
expect(redirects).toContain("/static /_next/pages/static.html 200")
183-
expect(redirects).toContain("/static/:id /_next/pages/static/[id].html 200")
183+
expect(redirects).toContain("/static /static.html 200")
184+
expect(redirects).toContain("/static/:id /static/[id].html 200")
184185
expect(redirects).toContain("/ /.netlify/functions/nextRouter 200")
185186
expect(redirects).toContain("/index /.netlify/functions/nextRouter 200")
186187
expect(redirects).toContain("/shows/:id /.netlify/functions/nextRouter 200")

tests/defaults.test.js

+23-9
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ beforeAll(
4141
join(PROJECT_PATH, "package.json")
4242
)
4343

44+
// Copy image.png to public folder
45+
copySync(
46+
join(FIXTURE_PATH, "image.png"),
47+
join(PROJECT_PATH, "public", "image.png")
48+
)
49+
4450
// Invoke `npm run build`: Build Next and run next-on-netlify
4551
const { stdout } = await npmRunBuild({ directory: PROJECT_PATH })
4652
BUILD_OUTPUT = stdout
@@ -154,33 +160,41 @@ describe('API Pages', () => {
154160
})
155161

156162
describe('Static Pages', () => {
157-
test('copies static pages to public/_next/ directory', () => {
158-
const pages = join(PROJECT_PATH, "public", "_next", "pages")
163+
test('copies static pages to output directory', () => {
164+
const OUTPUT_PATH = join(PROJECT_PATH, "out")
159165

160-
expect(existsSync(join(pages, "static.html"))).toBe(true)
161-
expect(existsSync(join(pages, "static/[id].html"))).toBe(true)
166+
expect(existsSync(join(OUTPUT_PATH, "static.html"))).toBe(true)
167+
expect(existsSync(join(OUTPUT_PATH, "static/[id].html"))).toBe(true)
162168
})
163169

164-
test('copies static assets to public/_next/ directory', () => {
165-
const dirs = readdirSync(join(PROJECT_PATH, "public", "_next", "static"))
170+
test('copies static assets to out/_next/ directory', () => {
171+
const dirs = readdirSync(join(PROJECT_PATH, "out", "_next", "static"))
166172

167173
expect(dirs.length).toBe(3)
168174
expect(dirs).toContain("chunks")
169175
expect(dirs).toContain("runtime")
170176
})
171177
})
172178

179+
describe('Public assets', () => {
180+
test('copies public files to output directory', () => {
181+
const OUTPUT_PATH = join(PROJECT_PATH, "out")
182+
183+
expect(existsSync(join(OUTPUT_PATH, "image.png"))).toBe(true)
184+
})
185+
})
186+
173187
describe('Routing',() => {
174188
test('creates Netlify redirects', async () => {
175189
// Read _redirects file
176-
const contents = readFileSync(join(PROJECT_PATH, "public", "_redirects"))
190+
const contents = readFileSync(join(PROJECT_PATH, "out", "_redirects"))
177191

178192
// Convert contents into an array, each line being one element
179193
const redirects = contents.toString().split("\n")
180194

181195
// Check that routes are present
182-
expect(redirects).toContain("/static /_next/pages/static.html 200")
183-
expect(redirects).toContain("/static/:id /_next/pages/static/[id].html 200")
196+
expect(redirects).toContain("/static /static.html 200")
197+
expect(redirects).toContain("/static/:id /static/[id].html 200")
184198
expect(redirects).toContain("/ /.netlify/functions/nextRouter 200")
185199
expect(redirects).toContain("/index /.netlify/functions/nextRouter 200")
186200
expect(redirects).toContain("/shows/:id /.netlify/functions/nextRouter 200")

tests/fixtures/image.png

16.3 KB
Loading

0 commit comments

Comments
 (0)