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

Add support for a custom _redirects file #21

Merged
merged 1 commit into from
Jun 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,12 @@ From now on, whenever you want to preview your application locally, just run:

#### Custom Netlify Redirects

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

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.
- `_redirects`
- `next-on-netlify` redirects
- `netlify.toml`

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

Expand Down
3 changes: 3 additions & 0 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const NEXT_DIST_DIR = getNextDistDir({ nextConfigPath: NEXT_CONFIG_PAT
// This is the Netlify Function template that wraps all SSR pages
const FUNCTION_TEMPLATE_PATH = join(__dirname, "netlifyFunctionTemplate.js")

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

module.exports = {
NETLIFY_PUBLISH_PATH,
Expand All @@ -31,4 +33,5 @@ module.exports = {
NEXT_CONFIG_PATH,
NEXT_DIST_DIR,
FUNCTION_TEMPLATE_PATH,
CUSTOM_REDIRECTS_PATH,
}
13 changes: 10 additions & 3 deletions lib/setupRedirects.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const path = require('path')
const { join } = path
const { writeFileSync } = require('fs-extra')
const { existsSync, readFileSync,
writeFileSync } = require('fs-extra')
const { default: isDynamicRoute } = require("@sls-next/lambda-at-edge/dist/lib/isDynamicRoute")
const { getSortedRoutes } = require("@sls-next/lambda-at-edge/dist/lib/sortedRoutes")
const { NETLIFY_PUBLISH_PATH } = require('./config')
const { NETLIFY_PUBLISH_PATH,
CUSTOM_REDIRECTS_PATH } = require('./config')
const allNextJsPages = require('./allNextJsPages')
const getNetlifyRoute = require('./getNetlifyRoute')
const getNetlifyFunctionName = require('./getNetlifyFunctionName')
Expand All @@ -30,6 +32,12 @@ const setupRedirects = () => {

// Generate redirects as array
const redirects = []
if(existsSync(CUSTOM_REDIRECTS_PATH)) {
console.log(" ", "# Prepending custom redirects")
redirects.push(readFileSync(CUSTOM_REDIRECTS_PATH))
}
redirects.push("# Next-on-Netlify Redirects")

sortedPages.forEach(page => {
// Generate redirect for each page route
page.routesAsArray.forEach(route => {
Expand Down Expand Up @@ -64,7 +72,6 @@ const setupRedirects = () => {
// Write redirects to _redirects file
writeFileSync(
join(NETLIFY_PUBLISH_PATH, "_redirects"),
"# Next-on-Netlify Redirects" + "\n" +
redirects.join("\n")
)
}
Expand Down
84 changes: 84 additions & 0 deletions tests/customRedirects.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Test next-on-netlify when a custom distDir is set in next.config.js
const { parse, join } = require('path')
const { copySync, emptyDirSync, readFileSync, writeFileSync } = require('fs-extra')
const npmRunBuild = require("./helpers/npmRunBuild")

// The name of this test file (without extension)
const FILENAME = parse(__filename).name

// The directory which will be used for testing.
// We simulate a NextJS app within that directory, with pages, and a
// package.json file.
const PROJECT_PATH = join(__dirname, "builds", FILENAME)

// The directory that contains the fixtures, such as NextJS pages,
// NextJS config, and package.json
const FIXTURE_PATH = join(__dirname, "fixtures")

// Capture the output of `npm run build` to verify successful build
let BUILD_OUTPUT

beforeAll(
async () => {
// Clear project directory
emptyDirSync(PROJECT_PATH)
emptyDirSync(join(PROJECT_PATH, "pages"))

// Copy NextJS pages and config
copySync(
join(FIXTURE_PATH, "pages-with-static-props-index"),
join(PROJECT_PATH, "pages")
)
copySync(
join(FIXTURE_PATH, "next.config.js"),
join(PROJECT_PATH, "next.config.js")
)

// Copy package.json
copySync(
join(FIXTURE_PATH, "package.json"),
join(PROJECT_PATH, "package.json")
)

// Create a _redirects file
writeFileSync(
join(PROJECT_PATH, "_redirects"),
"# Custom Redirect Rules\n" +
"https://old.example.com/* https://new.example.com/:splat 301!\n"
)

// Invoke `npm run build`: Build Next and run next-on-netlify
const { stdout } = await npmRunBuild({ directory: PROJECT_PATH })
BUILD_OUTPUT = stdout
},
// time out after 180 seconds
180 * 1000
)

describe('Next', () => {
test('builds successfully', () => {
// NextJS output
expect(BUILD_OUTPUT).toMatch("Creating an optimized production build...")
expect(BUILD_OUTPUT).toMatch("Automatically optimizing pages...")
expect(BUILD_OUTPUT).toMatch("First Load JS shared by all")

// Next on Netlify output
expect(BUILD_OUTPUT).toMatch("Next on Netlify")
expect(BUILD_OUTPUT).toMatch("Success! All done!")
})
})

describe('Routing',() => {
test('includes custom redirect rules', async () => {
// Read _redirects file
const contents = readFileSync(join(PROJECT_PATH, "out_publish", "_redirects"))

const redirects = contents.toString().split(/\n/)
expect(redirects[0]).toEqual("# Custom Redirect Rules")
expect(redirects[1]).toEqual("https://old.example.com/* https://new.example.com/:splat 301!")

// Check that other routes are present
expect(redirects).toContain("/ /index.html 200")
expect(redirects).toContain("/index /index.html 200")
})
})