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 devでhttp://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までの内容です。
続きはまた。