Next.js
Next.js is a lightweight framework for static and server‑rendered applications. https://nextjs.org
Server-side rendering


// create-react-app dev
curl localhost:3000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json">
<link rel="shortcut icon" href="/favicon.ico">
<!--
Notice the use of in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script type="text/javascript" src="/static/js/bundle.js"></script></body>
</html>
// create-react-app prod
curl localhost:3000
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000">
<link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico">
<title>React App</title>
<link href="/static/css/main.c17080f1.css" rel="stylesheet">
</head>
<body><noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root">
</div><script type="text/javascript" src="/static/js/main.d1cb61c2.js">
</script>
</body>
</html>

// next.js app
curl localhost:3000
<!DOCTYPE html>
<html>
<head>
<meta charSet="utf-8" class="next-head"/><link rel="preload" href="/_next/static/development/pages/index.js" as="script"/>
<link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/>
<link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/><link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/><link rel="preload" href="/_next/static/runtime/main.js" as="script"/></head>
<body>
<div id="__next"><div data-reactroot="">Welcome to next.js!</div></div>
<script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script>
<script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script></body></html>
Next.js
- Projet open source (https://github.com/zeit/next.js/)
- "Framework" car propose une structure
- Nuxt.js pour Vue
- Inspiré par PHP pour la simplicité

Quelques commandes
// package.json
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
// pages/index.js -> localhost:3000
export default () => <div>👋la bouffe front 😻</div>
Par convention, les composants dans le dossier /pages sont automatiquement routés et code splitté
// pages/cow.js -> localhost:3000/cow
import cowsay from 'cowsay-browser'
export default () =>
<pre>
{cowsay.say({ text: '🐄 there!' })}
</pre>
css
Par défaut styled-jsx, un peu comme .vue
Possibilité d'importer css, .scss, .less ou .styl
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>
Récupérer des données
Composants
import React from 'react'
export default class extends React.Component {
static async getInitialProps({ req }) {
const res = await fetch('https://api.github.com/repos/zeit/next.js')
const json = await res.json()
return { stars: json.stargazers_count }
}
render() {
const { stars } = this.props;
return (
<div>
<p>
👋 la bouffe front 😻
</p>
<p>
Next stars: {stars}
</p>
<Link prefetch href="/cow">
Meuh
</Link>{' '}
</div>
)
}
}
Possibilité d'exporter en HTML
// package.json
"scripts": {
"export": "next export",
"serve": "serve -s out"
},
Serveur custom
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer((req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl
if (pathname === '/a') {
app.render(req, res, '/b', query)
} else if (pathname === '/b') {
app.render(req, res, '/a', query)
} else {
handle(req, res, parsedUrl)
}
}).listen(3000, err => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
Un petit projet de démo
- Serveur express
- Appels à une API externe
- Mise en cache avec LRU-Cache
Avantages
- Vitesse d'affichage pour l'utilisateur 🚄
- SEO bon et cohérent 🔎
- Encapsule Webpack 📦
- Code splitting ✂️
- Mises à jour régulières 🔥
- Utilisé en prod et validé @hubside ✅
Inconvévients
- Besoin d'un serveur node 🖥️
- Peut avoir de mauvaise perf serveur 🐢(ReactDOMServer.renderToString appel CPU synchrone)
- Parfois des petits breaking change sympa 💥
- Complexifie le workflow 🕵️♂️

Quelques ressources
Exos avec QCM : https://nextjs.org/learn/
7 principles of rich web application : https://rauchg.com/2014/7-principles-of-rich-web-applications
Devtips : https://www.youtube.com/playlist?list=PLqGj3iMvMa4K-QGq9uaF3BbPojp4xyoRw
BOW 2018 - Nuxt.js : https://www.youtube.com/watch?v=VmYcHNIp4tM
Liste d'APIs publiques : https://github.com/toddmotto/public-apis
Repo perso avec les exemples utilisés dans la prez : https://github.com/alexbrbr/prez-next
Next.js
By Alexandre BARBIER
Next.js
- 984