JavaScript
React
next.js

Next.jsのインストールとルーティングの基礎


Next.jsとは?

Next.jsとは、Reactのユニバーサルフレームワークです。Nowでお馴染みのzeit.coが開発していて、以下のような特徴があります。


  • SSR(サーバーサイドレンダリング)

  • 高速なページロードのための自動コード分割

  • ページベースのクライアントサイドルーティング

  • webpackベースの開発環境で、Hot Module Replacement(HMR)をサポート

  • Express等のHTTPサーバーと一緒に実装可能

  • Babelやwebpackの設定をカスタマイズ可能

このエントリーでは、公式のチュートリアルをもとに、Next.jsのインストールと、ルーティングの基礎をまとめてみました。


インストール

$ mkdir hello-next

$ cd hello-next
$ npm init -y
$ npm install --save react react-dom next
$ mkdir pages

package.jsonには以下のnpm scriptsを記述します。

{

"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}

npm run devhttp://localhost:3000にローカルサーバーが立ち上がります。現在は404になっているので、簡単なページを追加してみましょう。

// pages/index.js

const Index = () => (
<div>
<p>Hello Next.js</p>
</div>
)

export default Index

ブラウザ上にHello Next.jsが表示されたかと思います。


ディレクトリの命名規則とルーティング

Next.jsでは、pagesディレクトリがルーティングの対象になります。それ以外のコンポーネントを配置するディレクトリ名にルールはなく、たとえばコンポーネント用のディレクトリは、componentsでも、compsでもなんでもOKです。


シンプルなルーティング

// pages/index.js

// This is the Link API
import Link from 'next/link'

const Index = () => (
<div>
<Link href="/about">
<a>About Page</a>
</Link>
<p>Hello Next.js</p>
</div>
)

export default Index

// pages/about.js

const About = () => {

// ヒストリーバックでもOK
const historyBack = () => {
history.back()
}

return (
<div>
<button onClick={historyBack}>History Back</button>
<p>This is About Page</p>
</div>
)
}

export default About


共通コンポーネントを使用

// components/Header.js

import Link from 'next/link'

// スタイル
const linkStyle = {
marginRight: 15
}

// ヘッダー用コンポーネント
const Header = () => (
<div>
<Link href="/">
<a style={linkStyle}>Home</a>
</Link>
<Link href="/about">
<a style={linkStyle}>About</a>
</Link>
</div>
)

export default Header

// pages/index.js

import Header from '../components/Header'

const Index = () => (
<div>
<Header />
<p>Hello Next.js</p>
</div>
)

export default Index

// pages/about.js

import Header from '../components/Header'

const About = () => (
<div>
<Header />
<p>This is About Page</p>
</div>
)

export default About


Layoutを継承

ベースとなるレイアウトコンポーネントを作成し、継承できます。ページコンポーネントの受け取り方はいくつかありますので、チュートリアルで紹介されているほうほうをご紹介します。


childrenでページコンポーネントを受け取る

// components/MyLayout.js

import Header from './Header'

const layoutStyle = {
margin: 20,
padding: 20,
border: '1px solid #DDD'
}

const Layout = props => (
<div style={layoutStyle}>
<Header />
{
// 引数でpages/*.jsのJSXを受け取る
props.children
}
</div>
)

export default Layout

// components/Header.js

import Link from 'next/link'

// スタイル
const linkStyle = {
marginRight: 15
}

// ヘッダー用コンポーネント
const Header = () => (
<div>
<Link href="/">
<a style={linkStyle}>Home</a>
</Link>
<Link href="/about">
<a style={linkStyle}>About</a>
</Link>
</div>
)

export default Header

// pages/index.js

import Layout from '../components/MyLayout'

const Index = () => (

// カスタムエレメントの小要素が渡される
<Layout>
<p>Hello Next.js</p>
</Layout>
)

export default Index

// pages/about.js

import Layout from '../components/MyLayout'

const About = () => (

// カスタムエレメントの小要素が渡される
<Layout>
<p>This is About Page</p>
</Layout>
)

export default About


ページコンポーネントをカスタムエレメントで受け取る

// components/MyLayout.js

import Header from './Header'

const layoutStyle = {
margin: 20,
padding: 20,
border: '1px solid #DDD'
}

const withLayout = Page => {
return () => (
<div style={layoutStyle}>
<Header />
<Page />
</div>
)
}

export default withLayout

// pages/index.js

import withLayout from '../components/MyLayout'

const Page = () => <p>Hello Next.js</p>

export default withLayout(Page)


// pages/about.js
import withLayout from '../components/MyLayout'

const Page = () => <p>This is the about page</p>

export default withLayout(Page)


contentでページコンポーネントを受け取る

// components/MyLayout.js

import Header from './Header'

const layoutStyle = {
margin: 20,
padding: 20,
border: '1px solid #DDD'
}

const Layout = props => (
<div style={layoutStyle}>
<Header />
{
// 引数でpages/*.jsのJSXを受け取る
props.content
}
</div>
)

export default Layout


// pages/index.js
import Layout from '../components/MyLayout.js'

const indexPageContent = <p>Hello Next.js</p>

export default function Index() {

// カスタムエレメントのpropsでJSXを渡す
return <Layout content={indexPageContent} />
}


// pages/about.js
import Layout from '../components/MyLayout.js'

const aboutPageContent = <p>This is the about page</p>

export default function About() {

// カスタムエレメントのpropsでJSXを渡す
return <Layout content={aboutPageContent} />
}

ちなみに、チュートリアルのUsing Shared Componentsまでの内容です。

続きはまた。