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

Commit f4a74d2

Browse files
committed
Add support for a custom _redirects file
Since _redirects always takes precedence over netlify.toml, allowing a custom _redirects file to be prepended to the published one is the only way to force a redirect of a path that matches content handled by next-on-netlify. This can be useful when using netlify to redirect from one domain to another.
1 parent 5edc905 commit f4a74d2

File tree

4 files changed

+102
-7
lines changed

4 files changed

+102
-7
lines changed

Diff for: README.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,12 @@ From now on, whenever you want to preview your application locally, just run:
118118

119119
#### Custom Netlify Redirects
120120

121-
You can define custom redirects in the `netlify.toml` file.
122-
Routes defined by `next-on-netlify` take precedence over routes
123-
defined in `netlify.toml`.
121+
You can define custom redirects in a `_redirects` and/or in your `netlify.toml` file.
122+
The precedence of these rules are:
124123

125-
In the past, it was possible to define custom redirects in a `_redirects` file. This is not possible anymore. Let me know if you have a need for this feature and we can add it back.
124+
- `_redirects`
125+
- `next-on-netlify` redirects
126+
- `netlify.toml`
126127

127128
[Read more about Netlify redirects here](https://docs.netlify.com/routing/redirects/).
128129

Diff for: lib/config.js

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const NEXT_DIST_DIR = getNextDistDir({ nextConfigPath: NEXT_CONFIG_PAT
2323
// This is the Netlify Function template that wraps all SSR pages
2424
const FUNCTION_TEMPLATE_PATH = join(__dirname, "netlifyFunctionTemplate.js")
2525

26+
// This is the file where custom redirects can be configured
27+
const CUSTOM_REDIRECTS_PATH = join(".", "_redirects")
2628

2729
module.exports = {
2830
NETLIFY_PUBLISH_PATH,
@@ -31,4 +33,5 @@ module.exports = {
3133
NEXT_CONFIG_PATH,
3234
NEXT_DIST_DIR,
3335
FUNCTION_TEMPLATE_PATH,
36+
CUSTOM_REDIRECTS_PATH,
3437
}

Diff for: lib/setupRedirects.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
const path = require('path')
22
const { join } = path
3-
const { writeFileSync } = require('fs-extra')
3+
const { existsSync, readFileSync,
4+
writeFileSync } = require('fs-extra')
45
const { default: isDynamicRoute } = require("@sls-next/lambda-at-edge/dist/lib/isDynamicRoute")
56
const { getSortedRoutes } = require("@sls-next/lambda-at-edge/dist/lib/sortedRoutes")
6-
const { NETLIFY_PUBLISH_PATH } = require('./config')
7+
const { NETLIFY_PUBLISH_PATH,
8+
CUSTOM_REDIRECTS_PATH } = require('./config')
79
const allNextJsPages = require('./allNextJsPages')
810
const getNetlifyRoute = require('./getNetlifyRoute')
911
const getNetlifyFunctionName = require('./getNetlifyFunctionName')
@@ -30,6 +32,12 @@ const setupRedirects = () => {
3032

3133
// Generate redirects as array
3234
const redirects = []
35+
if(existsSync(CUSTOM_REDIRECTS_PATH)) {
36+
console.log(" ", "# Prepending custom redirects")
37+
redirects.push(readFileSync(CUSTOM_REDIRECTS_PATH))
38+
}
39+
redirects.push("# Next-on-Netlify Redirects")
40+
3341
sortedPages.forEach(page => {
3442
// Generate redirect for each page route
3543
page.routesAsArray.forEach(route => {
@@ -64,7 +72,6 @@ const setupRedirects = () => {
6472
// Write redirects to _redirects file
6573
writeFileSync(
6674
join(NETLIFY_PUBLISH_PATH, "_redirects"),
67-
"# Next-on-Netlify Redirects" + "\n" +
6875
redirects.join("\n")
6976
)
7077
}

Diff for: tests/customRedirects.test.js

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Test next-on-netlify when a custom distDir is set in next.config.js
2+
const { parse, join } = require('path')
3+
const { copySync, emptyDirSync, readFileSync, writeFileSync } = require('fs-extra')
4+
const npmRunBuild = require("./helpers/npmRunBuild")
5+
6+
// The name of this test file (without extension)
7+
const FILENAME = parse(__filename).name
8+
9+
// The directory which will be used for testing.
10+
// We simulate a NextJS app within that directory, with pages, and a
11+
// package.json file.
12+
const PROJECT_PATH = join(__dirname, "builds", FILENAME)
13+
14+
// The directory that contains the fixtures, such as NextJS pages,
15+
// NextJS config, and package.json
16+
const FIXTURE_PATH = join(__dirname, "fixtures")
17+
18+
// Capture the output of `npm run build` to verify successful build
19+
let BUILD_OUTPUT
20+
21+
beforeAll(
22+
async () => {
23+
// Clear project directory
24+
emptyDirSync(PROJECT_PATH)
25+
emptyDirSync(join(PROJECT_PATH, "pages"))
26+
27+
// Copy NextJS pages and config
28+
copySync(
29+
join(FIXTURE_PATH, "pages-with-static-props-index"),
30+
join(PROJECT_PATH, "pages")
31+
)
32+
copySync(
33+
join(FIXTURE_PATH, "next.config.js"),
34+
join(PROJECT_PATH, "next.config.js")
35+
)
36+
37+
// Copy package.json
38+
copySync(
39+
join(FIXTURE_PATH, "package.json"),
40+
join(PROJECT_PATH, "package.json")
41+
)
42+
43+
// Create a _redirects file
44+
writeFileSync(
45+
join(PROJECT_PATH, "_redirects"),
46+
"# Custom Redirect Rules\n" +
47+
"https://old.example.com/* https://new.example.com/:splat 301!\n"
48+
)
49+
50+
// Invoke `npm run build`: Build Next and run next-on-netlify
51+
const { stdout } = await npmRunBuild({ directory: PROJECT_PATH })
52+
BUILD_OUTPUT = stdout
53+
},
54+
// time out after 180 seconds
55+
180 * 1000
56+
)
57+
58+
describe('Next', () => {
59+
test('builds successfully', () => {
60+
// NextJS output
61+
expect(BUILD_OUTPUT).toMatch("Creating an optimized production build...")
62+
expect(BUILD_OUTPUT).toMatch("Automatically optimizing pages...")
63+
expect(BUILD_OUTPUT).toMatch("First Load JS shared by all")
64+
65+
// Next on Netlify output
66+
expect(BUILD_OUTPUT).toMatch("Next on Netlify")
67+
expect(BUILD_OUTPUT).toMatch("Success! All done!")
68+
})
69+
})
70+
71+
describe('Routing',() => {
72+
test('includes custom redirect rules', async () => {
73+
// Read _redirects file
74+
const contents = readFileSync(join(PROJECT_PATH, "out_publish", "_redirects"))
75+
76+
const redirects = contents.toString().split(/\n/)
77+
expect(redirects[0]).toEqual("# Custom Redirect Rules")
78+
expect(redirects[1]).toEqual("https://old.example.com/* https://new.example.com/:splat 301!")
79+
80+
// Check that other routes are present
81+
expect(redirects).toContain("/ /index.html 200")
82+
expect(redirects).toContain("/index /index.html 200")
83+
})
84+
})

0 commit comments

Comments
 (0)