Next.js

Step 6: Preparing for release

Our website is almost ready now. One thing we need to make sure is that all pages have the required meta tags inside . Next.js provides a component for this and a special file where we can customize the overall page html (which is rendered once on the server side only).


Create a new file inside the directory. The default from looks like this:

We’ll modify it to include a favicon, update the file like this:

Upload the favicon.ico file to the directory.

Note: Meta tags for charset and viewport are added automatically by Next.js, it’s not necessary to add them manually.

What about meta tags that are page specific? We can use the component inside our pages as well. A recommended approach is to do it via the component. Edit the file and update it like this:

We’re adding the and tags based on the props sent to the from individual pages. If the page doesn’t set the title prop, it will be the default Fi Studio. Let’s update our pages to add the title prop to pages, change the existing line to:

You can add a prop as well if you want.

API

Creates a Context object. When React renders a component that subscribes to this Context object it will read the current context value from the closest matching above it in the tree.

The argument is only used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Note: passing as a Provider value does not cause consuming components to use .

Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes.

Accepts a prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree.

All consumers that are descendants of a Provider will re-render whenever the Provider’s prop changes. The propagation from Provider to its descendant consumers (including and ) is not subject to the method, so the consumer is updated even when an ancestor component skips an update.

Changes are determined by comparing the new and old values using the same algorithm as .

The property on a class can be assigned a Context object created by . This lets you consume the nearest current value of that Context type using . You can reference this in any of the lifecycle methods including the render function.

A React component that subscribes to context changes. This lets you subscribe to a context within a .

Requires a . The function receives the current context value and returns a React node. The argument passed to the function will be equal to the prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the argument will be equal to the that was passed to .

Context object accepts a string property. React DevTools uses this string to determine what to display for the context.

For example, the following component will appear as MyDisplayName in the DevTools:

Step 1: Setting up Next.js

We’ll install Next.js following instructions from . Make sure you have Node.js installed on your computer.

Create a new directory for the project anywhere on your computer (I’ll use ) and move into it via the Terminal, for example:

Once inside the directory, initialize a new Node.js project with :

Then run this command to install Next.js and React:

Open the whole project folder in a code editor of your choice (I recommend VS Code) and open the file, it should look something like this:

Next.js requires us to add several scripts to the package.json files to be able to build and run the website:

We’ll add them to the file like this:

Our website will consist of many React components. While React itself doesn’t require you to use a specific file structure, with Next.js you must create a directory where you’ll put a component file for every page of your website. Other components can be placed in other directories of your choice. For a website that we’re building, I recommend to keep it simple and create only two directories, for page components and for all other components.

Inside the directory, create an file which will become the homepage of our website. The file needs to contain a React component, we’ll name it :

The component returns JSX, a syntax extension to JavaScript which produces React Elements. I won’t exaplan JSX in detail, please read the official documentation article.

This is enough to check our progress. Run command in the Terminal and Next.js will build the website in development mode. It will be available on the http://localhost:3000 url. You should see something like this:

Before You Use Context

Context is primarily used when some data needs to be accessible by many components at different nesting levels. Apply it sparingly because it makes component reuse more difficult.

If you only want to avoid passing some props through many levels, component composition is often a simpler solution than context.

For example, consider a component that passes a and prop several levels down so that deeply nested and components can read it:

It might feel redundant to pass down the and props through many levels if in the end only the component really needs it. It’s also annoying that whenever the component needs more props from the top, you have to add them at all the intermediate levels too.

One way to solve this issue without context is to so that the intermediate components don’t need to know about the or props:

With this change, only the top-most Page component needs to know about the and components’ use of and .

This inversion of control can make your code cleaner in many cases by reducing the amount of props you need to pass through your application and giving more control to the root components. However, this isn’t the right choice in every case: moving more complexity higher in the tree makes those higher-level components more complicated and forces the lower-level components to be more flexible than you may want.

You’re not limited to a single child for a component. You may pass multiple children, or even have multiple separate “slots” for children, :

This pattern is sufficient for many cases when you need to decouple a child from its immediate parents. You can take it even further with render props if the child needs to communicate with the parent before rendering.


However, sometimes the same data needs to be accessible by many components in the tree, and at different nesting levels. Context lets you “broadcast” such data, and changes to it, to all components below. Common examples where using context might be simpler than the alternatives include managing the current locale, theme, or a data cache.

Step 3: Creating the site layout

Similarly how we included the into pages, we could also add other page elements like the Logo, Header, Footer, etc., but it’s not a good idea to include all those components into every page individually. Instead, we’ll create a single component that will contain those page elements and we’ll make our pages import only the component.

Here’s the plan for the site layout: individual pages will include the component. Layout component will include , and components. Header component will include a logo and the component. component will only contain page content. component will contain the copyright text.

First create a new component in a new file:

We imported the component from to be able to make the logo link to the homepage.

Next we’ll create the component in a new file and import our existing and components:

We’ll also need a component. Create a file and paste this code:

We could have created a separate component for the copyright text, but I don’t think it’s necessary as we won’t need it anywhere else and the footer won’t contain anything else.

Now that we have all the individual page elements, let’s create their parent component in a new file:

The will render the actual page content because we’ll wrap all content of our pages inside this new component. Edit all pages like this:

We no longer need the component inside our pages because it is included in the component, which is included in the component.

Check the site again and you should see the same thing as in the previous step, but with the addition of logo and copyright text:

Step 5: Adding content to pages

Now that we have the site structure completed with some basic styling, let’s add content to pages.

Services page

For the services pages we can create a small grid with 4 images to show what we do. Create a directory and upload these images into it. Then update the file like this:

The page should look something like this:

Portfolio page

This page can have a simple photo gallery of Fi Studio’s latest work. Instead of including all gallery photos directly on the Portfolio page, it’s better to create a separate component that can be reused on multiple pages.

Create a new file and add this code:

The component accepts an prop which is an array of image paths that we’ll pass from pages that will contain the gallery. We’re using CSS Flexbox to align images in two rows.

To include portfolio images to the Portfolio page, first upload the images into the directory. To keep things simple, I used numeric file names for images so that whenever we add more images, we would only need to update the image count in the Portfolio page to include new images.

Update the file to include the component:

We’re creating an array and populating it with image paths based on the overall image count.

The Portfolio page should look like this now:

About Us page

The About Us page will contain company info and some text about the company and a photo. Edit the file and add this code:

The single studio.jpg image should be uploaded to the directory.

The About Us page now looks like this:

Homepage

For the homepage we’ll add a nice cover image and we’ll reuse the existing component to include last 4 images from the Portfolio. Edit the file and update the code like this:

Upload the cover.jpg image to the directory. Above the cover there’s a a small Hello section with a link to the Services page. For the Latest Work section we’re including the component and passing it an array with paths to the last 4 images that we want to show.

Boilerplates

  • Nitro — An Example of a PWA using Nextjs, Material-UI, Typescript and Auth0
  • Next & Now 2.0 Typescript template — Serverless, Typescript, Jest, Github CI, SCSS, prettier boilerplate
  • Next Right Now — Flexible production-grade boilerplate with Next.js 9 and Vercel, with pre-configured Sentry, cookies, Amplitude, Emotion, FontAwesome, GraphQL/GraphCMS (Apollo), Bootstrap (Reactstrap), i18next (Locize), Jest, Cypress (E2E tests) and CI/CD (GH Actions), with full TypeScript support and support for B2B multi-tenants web apps (monorepo)
  • Next Graphql Apollo Typescript_Boostrap — Pobocha — React + GraphQL + Next.js + Apollo + Scss + Typescript + Prettier & EsLint boilerplate
  • Next & Vercel Typescript template — Serverless, Typescript, Jest, Github CI, SCSS, prettier boilerplate
  • NextJS in Firebase with Bootstrap — Hosting NextJS app with Bootstrap in Firebase with Cloud Functions.
  • Next Simple Starter — Simple PWA boilerplate with Next.js and Redux.
  • NextJS Starter — Starter project for Next.js with and email and oAuth authentication.
  • RAN! — Production-ready boilerplate with support for GraphQL, SSR, Hot-reload, CSS-in-JS, caching, and more.
  • Next Simple Blog — Simple Markdown based blog built with Next.js with static exports.
  • Create-Next-App — Fork of Facebook’s create-react-app to create a next application.
  • phox — Create a static photo blog.
  • Next Express Bootstrap Boilerplate — Boilerplate for a full stack app built using Next, Express, react-bootstrap, SCSS and SSR with eslint.
  • Next Blog Firestore — Blog with simple CMS built with Next.js, Firebase Firestore, styled-components and mobx-state-tree.
  • Next Redux Starter — Next.js starter with Express, Redux, and PostCSS.
  • NextJS Redux-Wrapper Material-UI — A boilerplate NextJS with Redux and Material UI.
  • Staart — Actively maintained Next.js components library and minimal boilerplate to rapidly get staarted with app with working user accounts based on Ooth.
  • NextJS TypeScript Starter Kit — :tada: TypeScript + NextJS, Styled-jsx, Redux, PostCSS, configurable SEO
  • Next Boilerplate — External CSS and Sass + Importing images from anywhere + Prettier and Eslint + Environment variables and many more features.
  • next-starter — A full and simple boilerplate with and built in.
  • Typescript Monorepo Next Example — A minimalistic next.js + typescript monorepo.
  • tomimick/tm-nextjs-starter — A minimal starter/demo with basic CRUD, axios/localstorage, MobX, SASS, static site export, live demo
  • csprance/next-smrt — A minimal boilerplate with redux, styled-components, material-ui and typescript with a custom express server.
  • Nextron — An Electron with Next.js apps generator
  • next-boilerplate — A well-structured production ready Next.js boilerplate with Typescript, Redux, Express.js, Sass, Css, EnvConfig, Reverse Proxy, Bundle
  • Oh My Fullstack — Full stack web application skeleton (Next.js, Redux, RxJS, Immutable, Express)
  • nextjs-mongodb-app — Full-fledged app made with Next.JS and MongoDB, with authentication and much more (Next.js 9, MongoDB)
  • react-next-boilerplate — :rocket: A basis for reducing the configuration of your projects with nextJS, best development practices and popular libraries in the developer community.
  • Apollo Next.js GraphQL starter — A GraphQL starter pack that uses Next.js, configured with Apollo Client
  • The-Nextjs-starter — typescript + redux + styled-components + react-testing-library + eslint + fontawesome
  • The Knests Stack — Full stack boilerplate/hackathon starter with: PostgreSQL, Knex.js, NestJS, Next.js (obviously), GraphQL, React (with hooks and typescript), Material-UI, Docker multistage images for, Docker compose and a Gitlab CI/CD pipeline fully configured.

Only JavaScript. Everything is a function

Every route within Next.js is simply a ES6 module that exports a function or class that extends from .

The advantages of this approach over similar models is that your entire system remains highly composable and testable. For example, a component can be rendered directly, or be imported and rendered by another top-level component.

Components can also introduce changes to the of the page:

Furthermore, no wrappers or transformations are needed to make this system fully testable. Your test suite can simply import and shallow-render your routes.

We’ve also made the decision to embrace CSS-in-JS. We use the excellent glamor library which gives us the full unconstrained power of CSS without the need for CSS parsing and compilation:

We think this model offers superior performance, composability and integration with the server-rendering pipeline. We cover this decision with more depth .

Apps

  • CourseLit — An open source alternative to Thinkific, Teachable etc.
  • Feednext — An open source social media application.
  • NextJS GOT — Simple Next.js application that showcases Game of Thrones Characters.
  • Next Episode — Sample Next.js app showing movie episodes.
  • Relate — Mindfulness community — React, GraphQL, Next.js.
  • Next News — HackerNews written in Next.js.
  • Password — One password, right way.
  • Next Todos — Todo list written in Next.js.
  • Hacker News — Another Hacker News written in Next.js.
  • Jet Chat — Jet and Next.js powered Chat demo.
  • Nextgram — Sample Next.js v2 app for showing off its capabilities.
  • Rauchg Blog — Blog built by a Next.js core maintainer.
  • Next JPH — JsonPlaceholder sample app made with Next.js.
  • Mailto — HTML mailto’s made easy.
  • Plate — The task management app to rule them all.
  • Dashboard — Create your own team dashboard with custom widgets.
  • Snape — A torrent client to search, stream and download torrents.
  • Trello Resume — Converts trello data into fast read information.
  • Server Authentication with JWT — Server authentication, prevent render before validation.
  • Alexander Kachkaev’s website – personal homepage built with Next.js, GraphQL, Docker and Kubernetes. Uses apollo client, react-intl, styled-components and recompose. Docker images are automatically built by GitLab CI.
  • Cookie handler with server render — Cookie handler with server render, access the cookie before render.
  • Gank — A Next.js App use gank-api, mobx and antd
  • Decoupled CMS example with GraphQL and Next.js
  • DS — Personal site manager.
  • Mozilla VR Home — Mozilla VR Home
  • Elton John’s website — Elton John’s Website
  • IOTA’s Data Market Place — IOTA Market Place
  • magicleap.com — Magic Leap
  • NPM.js Search Page — NPM’s Search Page
  • Docker Success Center — Docker Success Center
  • Urteile & Gesetze — German Legal Information System licensed under GPLv3.
  • TikTok’s HomePage — TikTok’s Home Page
  • njt.now.sh — npm jump to (package navigation shortcuts you dreamed about). Partially statically-rendered, partially deployed as lambda. Automatically updated on each commit to the github repo, thanks to Now integration.
  • caseconverter.pro — A text case converter.
  • Tottem — Bookmark manager on steroid built with NextJs / Auth0 / Apollo Tools / Prisma2

Step 2. Update getStaticProps

The next step is to update to support the preview mode.

If you request a page which has with the preview mode cookies set (via ), then will be called at request time (instead of at build time).

Furthermore, it will be called with a object where:

  • will be .
  • will be the same as the argument used for .

We used in the preview API route, so will be . You can use this to pass session information from the preview API route to if necessary.


If you’re also using , then will also be available.

You can update to fetch different data based on and/or .

For example, your headless CMS might have a different API endpoint for draft posts. If so, you can use to modify the API endpoint URL like below:

That’s it! If you access the preview API route (with and ) from your headless CMS or manually, you should now be able to see the preview content. And if you update your draft without publishing, you should be able to preview the draft.

getStaticPaths (Static Generation)

If a page has dynamic routes (documentation) and uses it needs to define a list of paths that have to be rendered to HTML at build time.

If you export an function called from a page that uses dynamic routes, Next.js will statically pre-render all the paths specified by .

The key determines which paths will be pre-rendered. For example, suppose that you have a page that uses dynamic routes named . If you export from this page and return the following for :

Then Next.js will statically generate and at build time using the page component in .

Note that the value for each must match the parameters used in the page name:

  • If the page name is , then should contain and .
  • If the page name uses catch-all routes, for example , then should contain which is an array. For example, if this array is , then Next.js will statically generate the page at .
  • If the page uses an optional catch-all route, supply , , or to render the root-most route. For example, if you supply for , Next.js will statically generate the page .

The object returned by must contain a boolean key.

If is , then any paths not returned by will result in a 404 page. You can do this if you have a small number of paths to pre-render — so they are all statically generated during build time. It’s also useful when the new pages are not added often. If you add more items to the data source and need to render the new pages, you’d need to run the build again.

Here’s an example which pre-renders one blog post per page called . The list of blog posts will be fetched from a CMS and returned by . Then, for each page, it fetches the post data from a CMS using . This example is also in the Pages documentation.

Examples

Static generation of a large number of pages

If is , then the behavior of changes:

  • The paths returned from will be rendered to HTML at build time.
  • The paths that have not been generated at build time will not result in a 404 page. Instead, Next.js will serve a “fallback” version of the page on the first request to such a path (see below for details).
  • In the background, Next.js will statically generate the requested path HTML and JSON. This includes running .
  • When that’s done, the browser receives the JSON for the generated path. This will be used to automatically render the page with the required props. From the user’s perspective, the page will be swapped from the fallback page to the full page.
  • At the same time, Next.js adds this path to the list of pre-rendered pages. Subsequent requests to the same path will serve the generated page, just like other pages pre-rendered at build time.

In the “fallback” version of a page:

  • The page’s props will be empty.
  • Using the router, you can detect if the fallback is being rendered, will be .

Here’s an example that uses :

is useful if your app has a very large number of static pages that depend on data (think: a very large e-commerce site). You want to pre-render all product pages, but then your builds would take forever.

Instead, you may statically generate a small subset of pages and use for the rest. When someone requests a page that’s not generated yet, the user will see the page with a loading indicator. Shortly after, finishes and the page will be rendered with the requested data. From now on, everyone who requests the same page will get the statically pre-rendered page.

This ensures that users always have a fast experience while preserving fast builds and the benefits of Static Generation.

will not update generated pages, for that take a look at .

You should use if you’re statically pre-rendering pages that use dynamic routes.

For TypeScript, you can use the type from :

When you use on a page with dynamic route parameters, you must use .

You cannot use with .

only runs at build time on server-side.

can only be exported from a page. You can’t export it from non-page files.

Also, you must use — it will not work if you add as a property of the page component.

In development (), will be called on every request.

Step 4: Styling the website

There are many different ways to write CSS for React & Next.js. I’ll compare different styling options in a future post. For this website we’ll use the library that’s included in Next.js by default. Basically, we’ll write the same CSS code as we used to for regular websites, but this time the CSS code will go inside special tags in our components.

The advantage of writing CSS with is that each page will include only the styles that it needs, which will reduce the overall page size and improve site performance.

We’ll use in individual components, but most sites need some global css styles that will be included on all pages. We can use for this.

For our website, the best place to put global css styles is in the component. Edit the file and update it like this:

We added with generic css styles before the closing tag of the component.

Our logo would be better if we replace the text with an image. All static files like images should be added to the directory. Create the directory and copy the logo.png file into it.

Edit the file and replace with and add alignment css styles like this:

Next, let’s update the file to add some padding and align its children elements with CSS Flexbox:

We also need to update the file to style the menu and align menu items horizontally:

We don’t need much for the Footer, other than aligning it to the center. Edit the file and add css styles like this:

The website looks a bit better now:

Step 2: Creating site pages and linking between them


Besides the homepage, our portfolio website will have 3 more pages: Services, Portfolio & About Us. Let’s create a new file for each one inside the pages directory:

Next.js by default creates a route for every file inside the directory. If you visit the http://localhost:3000/services url, the page should display Our Services.

Our next step is to make it possible to navigate between pages via menu links. Next.js provides a component for this. Let’s create a new component that will contain links to all pages:

Create a file and add this code into it:

We’re importing the component from and we created an unordered list with a link for every page. Keep in mind that the component must wrap regular tags.

To be able to click on menu links, we need to include this new component into our pages. Edit all files inside the directory, and add include the Menu like this:

Now you can click around to see the different pages:

Extensions

  • Next universal language detector — Language detector that works universally (browser + server) — Meant to be used with a universal framework, such as Next.js DEMO
  • Next Routes — Universal named routes for Next.js.
  • Next-Pkg — Extended Next.js server with pkg support.
  • Next Plugins — A curated list of plugins for Webpack and Next.js
  • Next Plugin Graphql — Next.js plugin for .graphql and .gql files using graphql-tag
  • Next With Apollo — Apollo Graphql integration for Next.js
  • Next SEO — SEO made easy for Next.js
  • Next UserAgent — UserAgent parser for Next.js
  • Next Cookie — Cookie serializer and deserializer library for Next.js.
  • Nextein — A static site generator based in Next.js.
  • next-mdx-blog — Easily add a blog to any next.js based project
  • next-routes-middleware — A NextJS routing middleware
  • Serverless Framework plugin for Next.js — Deploy serverless applications with ease.
  • Terraform For Next.js — Deploy your application using Terraform
  • next-session — Session middleware for Next.js
  • next-iron-session — Next.js stateless session utility using signed and encrypted cookies to store data
  • Next PurgeCSS — Easily integrate Purgecss, which helps you remove unused CSS from your bundle.
  • Next PWA — Zero config PWA plugin for Next.js with workbox
  • flow-middleware — Run any of Express middlewares on Next.js without polluting native objects.

getStaticProps (Static Generation)

If you export an function called from a page, Next.js will pre-render this page at build time using the props returned by .

The parameter is an object containing the following keys:

  • contains the route parameters for pages using dynamic routes. For example, if the page name is , then will look like . To learn more, take a look at the Dynamic Routing documentation. You should use this together with , which we’ll explain later.
  • is if the page is in the preview mode and otherwise. See the Preview Mode documentation.
  • contains the preview data set by . See the Preview Mode documentation.

should return an object with:

  • — A required object with the props that will be received by the page component. It should be a serializable object
  • — An optional amount in seconds after which a page re-generation can occur. More on

Here’s an example which uses to fetch a list of blog posts from a CMS (content management system). This example is also in the Pages documentation.

You should use if:

  • The data required to render the page is available at build time ahead of a user’s request.
  • The data comes from a headless CMS.
  • The data can be publicly cached (not user-specific).
  • The page must be pre-rendered (for SEO) and be very fast — generates HTML and JSON files, both of which can be cached by a CDN for performance.

For TypeScript, you can use the type from :

If you want to get inferred typings for your props, you can use , like this:

Examples

Static Reactions Demo

With you don’t have to stop relying on dynamic content, as static content can also be dynamic. Incremental Static Regeneration allows you to update existing pages by re-rendering them in the background as traffic comes in.

Inspired by stale-while-revalidate, background regeneration ensures traffic is served uninterruptedly, always from static storage, and the newly built page is pushed only after it’s done generating.

Consider our previous , but now with regeneration enabled:

Now the list of blog posts will be revalidated once per second; if you add a new blog post it will be available almost immediately, without having to re-build your app or make a new deployment.

This works perfectly with . Because now you can have a list of posts that’s always up to date with the latest posts, and have a that generates blog posts on-demand, no matter how many posts you add or update.

Unlike traditional SSR, ensures you retain the benefits of static:

  • No spikes in latency. Pages are served consistently fast
  • Pages never go offline. If the background page re-generation fails, the old page remains unaltered
  • Low database and backend load. Pages are re-computed at most once concurrently

Files can be read directly from the filesystem in .

In order to do so you have to get the full path to a file.

Since Next.js compiles your code into a separate directory you can’t use as the path it will return will be different from the pages directory.

Instead you can use which gives you the directory where Next.js is being executed.

Because runs at build time, it does not receive data that’s only available during request time, such as query parameters or HTTP headers as it generates static HTML.

Note that runs only on the server-side. It will never be run on the client-side. It won’t even be included in the JS bundle for the browser. That means you can write code such as direct database queries without them being sent to browsers. You should not fetch an API route from — instead, you can write the server-side code directly in .

You can use this tool to verify what Next.js eliminates from the client-side bundle.

When a page with is pre-rendered at build time, in addition to the page HTML file, Next.js generates a JSON file holding the result of running .

This JSON file will be used in client-side routing through (documentation) or (documentation). When you navigate to a page that’s pre-rendered using , Next.js fetches this JSON file (pre-computed at build time) and uses it as the props for the page component. This means that client-side page transitions will not call as only the exported JSON is used.

can only be exported from a page. You can’t export it from non-page files.

One of the reasons for this restriction is that React needs to have all the required data before the page is rendered.

Also, you must use — it will not work if you add as a property of the page component.

In development (), will be called on every request.

In some cases, you might want to temporarily bypass Static Generation and render the page at request time instead of build time. For example, you might be using a headless CMS and want to preview drafts before they’re published.

This use case is supported by Next.js by the feature called Preview Mode. Learn more on the Preview Mode documentation.


С этим читают