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

Allow the main index route to be ssg rendered with getStaticProps #18

Merged
merged 1 commit into from
Jun 14, 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
17 changes: 15 additions & 2 deletions lib/allNextJsPages.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ const getAllPages = () => {
return

// Skip page if it is actually an SSG page
if(route in staticSsgPages || route in dynamicSsgPages)
const normalizedRoute = route === "/index" ? "/" : route
if(normalizedRoute in staticSsgPages || normalizedRoute in dynamicSsgPages)
return

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

// Parse SSG pages
Object.entries(staticSsgPages).forEach(([ route, { dataRoute }]) => {
pages.push(new Page({ route, type: "ssg", dataRoute }))
pages.push(new Page({ route, type: "ssg", dataRoute, alternativeRoutes: route === "/" ? ["/index"] : [] }))
})
Object.entries(dynamicSsgPages).forEach(([ route, { dataRoute, fallback }]) => {
// Ignore pages without fallback, these are already handled by the
Expand Down Expand Up @@ -100,6 +101,18 @@ class Page {
return this.type === "ssg-fallback"
}

routeFile(ext) {
return `${this.route.replace(/^\/$/, '/index')}${ext}`
}

get htmlFile() {
return this.routeFile(".html")
}

get jsonFile() {
return this.routeFile(".json")
}

// Return route and alternative routes as array
get routesAsArray() {
return [this.route, ...this.alternativeRoutes]
Expand Down
2 changes: 1 addition & 1 deletion lib/setupRedirects.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const setupRedirects = () => {
}
// SSG pages
else if (page.isSsg()) {
to = `${page.route}.html`
to = page.htmlFile
}
// SSG fallback pages (for non pre-rendered paths)
else if (page.isSsgFallback()) {
Expand Down
10 changes: 5 additions & 5 deletions lib/setupSsgPages.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ const setupSsgPages = () => {
// Copy pre-rendered SSG pages to Netlify publish folder
console.log(" ", "1. Copying pre-rendered SSG pages to", NETLIFY_PUBLISH_PATH)

ssgPages.forEach(({ route }) => {
const filePath = join("pages", `${route}.html`)
ssgPages.forEach(({ htmlFile }) => {
const filePath = join("pages", htmlFile)
console.log(" ", " ", filePath)

copySync(
join(NEXT_DIST_DIR, "serverless", filePath),
join(NETLIFY_PUBLISH_PATH, `${route}.html`),
join(NETLIFY_PUBLISH_PATH, htmlFile),
{
overwrite: false,
errorOnExist: true
Expand All @@ -36,8 +36,8 @@ const setupSsgPages = () => {
const nextDataFolder = join(NETLIFY_PUBLISH_PATH, "_next", "data/")
console.log(" ", "2. Copying SSG page data to", nextDataFolder)

ssgPages.forEach(({ route, dataRoute }) => {
const dataPath = join("pages", `${route}.json`)
ssgPages.forEach(({ jsonFile, dataRoute }) => {
const dataPath = join("pages", jsonFile)
console.log(" ", " ", dataPath)

copySync(
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions tests/__snapshots__/defaults.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

exports[`Routing creates Netlify redirects 1`] = `
"# Next-on-Netlify Redirects
/api/static /.netlify/functions/next_api_static 200
/getServerSideProps/static /.netlify/functions/next_getServerSideProps_static 200
/_next/data/%BUILD_ID%/getServerSideProps/static.json /.netlify/functions/next_getServerSideProps_static 200
/index /.netlify/functions/next_index 200
/ /.netlify/functions/next_index 200
/static /static.html 200
/404 /404.html 200
/_next/data/%BUILD_ID%/getServerSideProps/:id.json /.netlify/functions/next_getServerSideProps_id 200
/_next/data/%BUILD_ID%/getServerSideProps/static.json /.netlify/functions/next_getServerSideProps_static 200
/_next/data/%BUILD_ID%/getStaticProps/withFallback/:id.json /.netlify/functions/next_getStaticProps_withFallback_id 200
/api/shows/* /.netlify/functions/next_api_shows_params 200
/api/shows/:id /.netlify/functions/next_api_shows_id 200
/api/static /.netlify/functions/next_api_static 200
/getServerSideProps/:id /.netlify/functions/next_getServerSideProps_id 200
/getServerSideProps/static /.netlify/functions/next_getServerSideProps_static 200
/getStaticProps/1 /getStaticProps/1.html 200
/getStaticProps/2 /getStaticProps/2.html 200
/getStaticProps/static /getStaticProps/static.html 200
/getStaticProps/withFallback/3 /getStaticProps/withFallback/3.html 200
/getStaticProps/withFallback/4 /getStaticProps/withFallback/4.html 200
/api/shows/:id /.netlify/functions/next_api_shows_id 200
/api/shows/* /.netlify/functions/next_api_shows_params 200
/getServerSideProps/:id /.netlify/functions/next_getServerSideProps_id 200
/_next/data/%BUILD_ID%/getServerSideProps/:id.json /.netlify/functions/next_getServerSideProps_id 200
/getStaticProps/withFallback/:id /.netlify/functions/next_getStaticProps_withFallback_id 200
/_next/data/%BUILD_ID%/getStaticProps/withFallback/:id.json /.netlify/functions/next_getStaticProps_withFallback_id 200
/shows/:id /.netlify/functions/next_shows_id 200
/index /.netlify/functions/next_index 200
/shows/* /.netlify/functions/next_shows_params 200
/shows/:id /.netlify/functions/next_shows_id 200
/static /static.html 200
/static/:id /static/[id].html 200"
`;
3 changes: 3 additions & 0 deletions tests/defaults.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ describe('Routing',() => {
// Replace non-persistent build ID with placeholder
redirects = redirects.replace(/\/_next\/data\/[^\/]+\//g, "/_next/data/%BUILD_ID%/")

// Sort contents for a stable comparison
redirects = redirects.split(/\n/).sort().join("\n")

// Check that redirects match
expect(redirects).toMatchSnapshot()
})
Expand Down
21 changes: 21 additions & 0 deletions tests/fixtures/pages-with-static-props-index/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Link from 'next/link'

const Page = ({ now }) => (
<div>
<h1>Date.now(): {now}</h1>

<Link href="/static">
<a>Static page</a>
</Link>
</div>
)

export async function getStaticProps(context) {
return {
props: {
now: Date.now()
}
}
}

export default Page
21 changes: 21 additions & 0 deletions tests/fixtures/pages-with-static-props-index/static/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Link from 'next/link'

const Page = ({ now }) => (
<div>
<h1>Date.now(): {now}</h1>

<Link href="/">
<a>Index page</a>
</Link>
</div>
)

export async function getStaticProps(context) {
return {
props: {
now: Date.now()
}
}
}

export default Page
110 changes: 110 additions & 0 deletions tests/staticIndexPages.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Test that next-on-netlify does not crash when pre-rendering index.js file
// with getStaticProps.

const { parse, join } = require('path')
const { copySync, emptyDirSync, existsSync,
readdirSync, readFileSync, readJsonSync } = 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")
)

// 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('Static Pages', () => {
test('copies static pages to output directory', () => {
const OUTPUT_PATH = join(PROJECT_PATH, "out_publish")

expect(existsSync(join(OUTPUT_PATH, "index.html"))).toBe(true)
expect(existsSync(join(OUTPUT_PATH, "static.html"))).toBe(true)
})

test('copies static assets to out_publish/_next/ directory', () => {
const dirs = readdirSync(join(PROJECT_PATH, "out_publish", "_next", "static"))

expect(dirs.length).toBe(3)
expect(dirs).toContain("chunks")
expect(dirs).toContain("runtime")
})
})

describe('404 Page', () => {
test('copies 404.html to output directory', () => {
const OUTPUT_PATH = join(PROJECT_PATH, "out_publish")

expect(existsSync(join(OUTPUT_PATH, "404.html"))).toBe(true)
})

// This is required for 404.html to work on netlify-dev
test('copies 404.html to directory root', () => {
expect(existsSync(join(PROJECT_PATH, "404.html"))).toBe(true)
})
})

describe('Routing',() => {
test('creates Netlify redirects', async () => {
// Read _redirects file
const contents = readFileSync(join(PROJECT_PATH, "out_publish", "_redirects"))

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

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