diff --git a/lib/router/index.js b/lib/router/index.js
index 8fa37e7d..30168ec4 100644
--- a/lib/router/index.js
+++ b/lib/router/index.js
@@ -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}`
}
diff --git a/readme.md b/readme.md
index 676d21ea..ab05d071 100644
--- a/readme.md
+++ b/readme.md
@@ -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' } }
@@ -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:
diff --git a/server/export.js b/server/export.js
index f911a687..1e95e160 100644
--- a/server/export.js
+++ b/server/export.js
@@ -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'
@@ -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)
diff --git a/test/integration/static/next.config.js b/test/integration/static/next.config.js
index 7c6fa0f9..dedaf9f5 100644
--- a/test/integration/static/next.config.js
+++ b/test/integration/static/next.config.js
@@ -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' } }
}
}
}
diff --git a/test/integration/static/pages/index.js b/test/integration/static/pages/index.js
index b1ecde62..cfd19908 100644
--- a/test/integration/static/pages/index.js
+++ b/test/integration/static/pages/index.js
@@ -44,6 +44,12 @@ export default () => (
>
With Hash
+
+ Path with extension
+
Level1 home page
diff --git a/test/integration/static/test/ssr.js b/test/integration/static/test/ssr.js
index 3a46ba44..b08ebbb3 100644
--- a/test/integration/static/test/ssr.js
+++ b/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', () => {
@@ -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/)
@@ -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() => {