Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow use of filenames in exportPathMap #2973

Merged
merged 5 commits into from Oct 5, 2017
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion lib/router/index.js
Expand Up @@ -101,7 +101,12 @@ export function _rewriteUrlForNextExport (url) {
let [path, qs] = url.split('?')
path = path.replace(/\/$/, '')

let newPath = `${path}/`
let newPath = path
// Append a trailing slash if this path does not have an extension
if (!/\.[^/]+\/?$/.test(path)) {
newPath = `${path}/`
}

if (qs) {
newPath = `${newPath}?${qs}`
}
Expand Down
3 changes: 3 additions & 0 deletions readme.md
Expand Up @@ -1064,6 +1064,7 @@ module.exports = {
return {
'/': { page: '/' },
'/about': { page: '/about' },
'/readme.md': { page: '/readme' },
'/p/hello-nextjs': { page: '/post', query: { title: 'hello-nextjs' } },
'/p/learn-nextjs': { page: '/post', query: { title: 'learn-nextjs' } },
'/p/deploy-nextjs': { page: '/post', query: { title: 'deploy-nextjs' } }
Expand All @@ -1072,6 +1073,8 @@ module.exports = {
}
```

> Note that if the path ends with a directory, it will be exported as `/dir-name/index.html`, but if it ends with an extension, it will be exported as the specified filename, e.g. `/readme.md` above. If you use a file extension other than `.html`, you may need to set the `Content-Type` header to `text/html` when serving this content.

In that, you specify what are the pages you need to export as static HTML.

Then simply run these commands:
Expand Down
11 changes: 9 additions & 2 deletions server/export.js
Expand Up @@ -2,7 +2,7 @@ import del from 'del'
import cp from 'recursive-copy'
import mkdirp from 'mkdirp-then'
import walk from 'walk'
import { resolve, join, dirname, sep } from 'path'
import { extname, resolve, join, dirname, sep } from 'path'
import { existsSync, readFileSync, writeFileSync } from 'fs'
import getConfig from './config'
import { renderToHTML } from './render'
Expand Down Expand Up @@ -96,7 +96,14 @@ export default async function (dir, options, configuration) {
const req = { url: path }
const res = {}

const htmlFilename = path === '/' ? 'index.html' : `${path}${sep}index.html`
let htmlFilename = `${path}${sep}index.html`
if (extname(path) !== '') {
// If the path has an extension, use that as the filename instead
htmlFilename = path
} else if (path === '/') {
// If the path is the root, just use index.html
htmlFilename = 'index.html'
}
const baseDir = join(outDir, dirname(htmlFilename))
const htmlFilepath = join(outDir, htmlFilename)

Expand Down
3 changes: 2 additions & 1 deletion test/integration/static/next.config.js
Expand Up @@ -9,7 +9,8 @@ module.exports = {
'/dynamic-imports': { page: '/dynamic-imports' },
'/dynamic': { page: '/dynamic', query: { text: 'cool dynamic text' } },
'/dynamic/one': { page: '/dynamic', query: { text: 'next export is nice' } },
'/dynamic/two': { page: '/dynamic', query: { text: 'zeit is awesome' } }
'/dynamic/two': { page: '/dynamic', query: { text: 'zeit is awesome' } },
'/file-name.md': { page: '/dynamic', query: { text: 'this file has an extension' } }
}
}
}
6 changes: 6 additions & 0 deletions test/integration/static/pages/index.js
Expand Up @@ -44,6 +44,12 @@ export default () => (
>
<a id='with-hash'>With Hash</a>
</Link>
<Link
href='/dynamic?text=this+file+has+an+extension'
as='/file-name.md'
>
<a id='path-with-extension'>Path with extension</a>
</Link>
<Link href='/level1'>
<a id='level1-home-page'>Level1 home page</a>
</Link>
Expand Down
17 changes: 16 additions & 1 deletion test/integration/static/test/ssr.js
@@ -1,5 +1,6 @@
/* global describe, it, expect */
import { renderViaHTTP } from 'next-test-utils'
import cheerio from 'cheerio'

export default function (context) {
describe('Render via SSR', () => {
Expand All @@ -8,6 +9,15 @@ export default function (context) {
expect(html).toMatch(/This is the home page/)
})

it('should render links correctly', async () => {
const html = await renderViaHTTP(context.port, '/')
const $ = cheerio.load(html)
const dynamicLink = $('#dynamic-1').prop('href')
const filePathLink = $('#path-with-extension').prop('href')
expect(dynamicLink).toEqual('/dynamic/one/')
expect(filePathLink).toEqual('/file-name.md')
})

it('should render a page with getInitialProps', async() => {
const html = await renderViaHTTP(context.port, '/dynamic')
expect(html).toMatch(/cool dynamic text/)
Expand All @@ -20,7 +30,12 @@ export default function (context) {

it('should render pages with dynamic imports', async() => {
const html = await renderViaHTTP(context.port, '/dynamic-imports')
expect(html).toMatch(/Welcome to dynamic imports./)
expect(html).toMatch(/Welcome to dynamic imports/)
})

it('should render paths with extensions', async() => {
const html = await renderViaHTTP(context.port, '/file-name.md')
expect(html).toMatch(/this file has an extension/)
})

it('should give empty object for query if there is no query', async() => {
Expand Down