Skip to content

Commit 2b9944b

Browse files
sergiodxatimneutkens
authored andcommitted
Add with-static-export example (vercel#2234)
1 parent 75de0fa commit 2b9944b

File tree

8 files changed

+172
-0
lines changed

8 files changed

+172
-0
lines changed

examples/with-static-export/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Static export example
2+
3+
## How to use
4+
5+
Download the example [or clone the repo](https://github.com/zeit/next.js):
6+
7+
```bash
8+
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/with-static-export
9+
cd with-static-export
10+
```
11+
12+
Install it and run:
13+
14+
```bash
15+
npm install
16+
npm run dev
17+
```
18+
19+
## The idea behind the example
20+
21+
This example show how to export to static HTML files your Next.js application fetching data from an API to generate a dynamic list of pages. This use a custom Express server in development to configure custom routing and then generate a map of pages to export for production.
22+
23+
When trying to run `npm start` it will build and export your pages into the `out` folder and serve them on `localhost:5000`.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Link from 'next/link'
2+
3+
export default props =>
4+
<article>
5+
<h2>{props.title}</h2>
6+
<p>{props.body}</p>
7+
{/* render the URL as /post/:id */}
8+
<Link href={{ pathname: '/post', query: { id: props.id } }} as={`/post/${props.id}`}>
9+
<a>Read more...</a>
10+
</Link>
11+
</article>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const fetch = require('isomorphic-fetch')
2+
3+
module.exports = {
4+
async exportPathMap () {
5+
// we fetch our list of posts, this allow us to dynamically generate the exported pages
6+
const response = await fetch('http://jsonplaceholder.typicode.com/posts?_page=1')
7+
const postList = await response.json()
8+
9+
// tranform the list of posts into a map of pages with the pathname `/post/:id`
10+
const pages = postList.reduce(
11+
(pages, post) =>
12+
Object.assign({}, pages, {
13+
[`/post/${post.id}`]: {
14+
page: '/post',
15+
query: { id: post.id }
16+
}
17+
}),
18+
{},
19+
)
20+
21+
// combine the map of post pages with the home
22+
return Object.assign({}, pages, {
23+
'/': { page: '/' }
24+
})
25+
}
26+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"main": "server.js",
3+
"dependencies": {
4+
"express": "^4.15.3",
5+
"isomorphic-fetch": "^2.2.1",
6+
"next": "beta",
7+
"react": "^15.5.4",
8+
"react-dom": "^15.5.4",
9+
"serve": "^5.2.2"
10+
},
11+
"scripts": {
12+
"dev": "node .",
13+
"build": "next build",
14+
"preexport": "npm run build",
15+
"export": "next export",
16+
"prestart": "npm run export",
17+
"start": "serve out"
18+
},
19+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Component } from 'react'
2+
import Head from 'next/head'
3+
import fetch from 'isomorphic-fetch'
4+
5+
import Post from '../components/post'
6+
7+
export default class extends Component {
8+
static async getInitialProps () {
9+
// fetch list of posts
10+
const response = await fetch('http://jsonplaceholder.typicode.com/posts?_page=1')
11+
const postList = await response.json()
12+
return { postList }
13+
}
14+
15+
render () {
16+
return (
17+
<main>
18+
<Head>
19+
<title>Home page</title>
20+
</Head>
21+
22+
<h1>List of posts</h1>
23+
24+
<section>
25+
{this.props.postList.map(post => <Post {...post} key={post.id} />)}
26+
</section>
27+
</main>
28+
)
29+
}
30+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Component } from 'react'
2+
import Link from 'next/link'
3+
import Head from 'next/head'
4+
import fetch from 'isomorphic-fetch'
5+
6+
export default class extends Component {
7+
static async getInitialProps ({ query }) {
8+
// fetch single post detail
9+
const response = await fetch(`http://jsonplaceholder.typicode.com/posts/${query.id}`)
10+
const post = await response.json()
11+
return { ...post }
12+
}
13+
14+
render () {
15+
return (
16+
<main>
17+
<Head>
18+
<title>{this.props.title}</title>
19+
</Head>
20+
21+
<h1>{this.props.title}</h1>
22+
23+
<p>{this.props.body}</p>
24+
25+
<Link href='/'>
26+
<a>Go back to home</a>
27+
</Link>
28+
</main>
29+
)
30+
}
31+
}

examples/with-static-export/server.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const express = require('express')
2+
const next = require('next')
3+
4+
const dev = process.env.NODE_ENV !== 'production'
5+
const app = next({ dev })
6+
const handle = app.getRequestHandler()
7+
8+
app.prepare()
9+
.then(() => {
10+
const server = express()
11+
12+
// custom route for posts
13+
server.get('/post/:id', (req, res) => {
14+
return app.render(req, res, '/post', {
15+
id: req.params.id
16+
})
17+
})
18+
19+
server.get('*', (req, res) => {
20+
return handle(req, res)
21+
})
22+
23+
server.listen(3000, (err) => {
24+
if (err) throw err
25+
console.log('> Ready on http://localhost:3000')
26+
})
27+
})

readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,11 @@ Note: we recommend putting `.next`, or your custom dist folder (Please have a lo
904904

905905
## Static HTML export
906906

907+
<p><details>
908+
<summary><b>Examples</b></summary>
909+
<ul><li><a href="./examples/with-static-export">Static export</a></li></ul>
910+
</details></p>
911+
907912
This is a way to run your Next.js app as a standalone static app without any Node.js server. The export app supports almost every feature of Next.js including dynamic urls, prefetching, preloading and dynamic imports.
908913

909914
### Usage

0 commit comments

Comments
 (0)