@_nati
SSR
universal
isomorphic
Setup
> mkdir my-next-app
> cd my-next-app
> yarn init -y
> yarn add react react-dom next@beta
> mkdir pages
{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}
package.json
Pages
pages/index.js
export default () => (
<div>Welcome to next.js!</div>
)
// pages/index.js
export default () => (
<div>
Hello world
<p>scoped!</p>
<style jsx>{`
p {
color: blue;
}
div {
background: red;
}
@media (max-width: 600px) {
div {
background: blue;
}
}
`}</style>
<style global jsx>{`
body {
background: black;
}
`}</style>
</div>
)
Populating <head>
import Head from 'next/head'
export default () => (
<div>
<Head>
<title>My page title</title>
</Head>
<p>Hello world!</p>
</div>
)
Simple Fetching data
import fetch from 'isomorphic-unfetch'
const Page = ({ stars }) => (
<div>Next stars: {stars}</div>
)
Page.getInitialProps = async ({ req }) => {
const res = await fetch('https://api.github.com/repos/zeit/next.js')
const json = await res.json()
return { stars: json.stargazers_count }
}
export default Page
getInitialProps
receives a context object with the following properties:
- pathname - path section of URL
- query - query string section of URL parsed as an object
- asPath - the actual url path
- req - HTTP request object (server only)
- res - HTTP response object (server only)
- jsonPageRes - Fetch Response object (client only)
- err - Error object if any error is encountered during the rendering
const Page = ({pathname, query}) => (
<div>
<pre>{JSON.stringify(pathname)}</pre>
<pre>{JSON.stringify(query)}</pre>
</div>
)
Page.getInitialProps = async ({pathname, query}) => {
return {
pathname,
query
}
}
export default Page
getInitialProps
Routing
next/link
import Link from 'next/link'
export default () => (
<Link href="/about"><a>About</a></Link>
)
next/router
import Router from 'next/router'
export default () => (
<span onClick={() => Router.push('/about')}>here</span>
)
Dynamic Pages
// pages/post.js
export default (props) => (
<div>
<h1>{props.url.query.title}</h1>
</div>
)
http://localhost:3000/post?title=Hello%20Next.js
http://localhost:3000/post?title=Hello%20Next.js
http://localhost:3000/p/hello-nextjs
vs
Clean URLs with Route Masking
// pages/index.js
export default () => (
<Link as={'/p/hello-nextjs'} href={'/post?title=Hello%20Next.js'}>
<a>Hello Next.js</a>
</Link>
)
Server Side Support for Clean URLs
// server.js
const express = require('express')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
server.get('/p/:id', (req, res) => {
const actualPage = '/post'
const queryParams = { title: req.params.id }
app.render(req, res, actualPage, queryParams)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})
// package.json
"scripts": {
"start": "NODE_ENV=production node server.js"
}
// next.config.js
module.exports = {
exportPathMap: function () {
return {
"/": { page: "/" },
"/p/hello-nextjs": { page: "/post", query: { title: "hello-nextjs" } }
}
}
}
Static HTML export
// package.json
"scripts": {
"build": "next build && next export"
}
// package.json
"scripts": {
"deploy": "next build && next export && node_modules/gh-pages/bin/gh-pages -d out"
}
> yarn add gh-pages
> yarn deploy
Deploy Static Web to Github Pages
Next.js | React BKK 2.0
By Nati Namvong
Next.js | React BKK 2.0
- 1,124