Next.jsのチュートリアルをよむ
2019/2/16
チュートリアルをおえた感想kadoyau.icon
Getting Started
Syntax errorがブラウザに出る
HMRがデフォルトでサポートされている(Webpackを使っている) Navigate Between Pages
ページ遷移したいときはLink APIを使う
pageを作りたいときにはpagesディレクトリにコンポーネントを作成してexport defaultする
このディレクトリは唯一、名前を変えることはできない(他のディレクトリは任意の名前をつけることができる)
ファイル名がURLになる。pages/about.jsなら/aboutでその内容を表示する
aタグ使えるけどサーバーサイド経由でnavigateされてクライアントサイドでnavigateされない
Linkを使うとサーバサイドにリクエストがいかない
https://gyazo.com/2e282cf486a6e879fe2adeb71aee5160
ページ中のリンクはLink APIで実装されている。このときNetworkの通信ログがない
Backボタンを押したら履歴が残っていて、戻る(サーバにリクエストも飛ばない)
next/linkは"href"などしかうけとらないHOCだからstyleはあたらない code:js
<Link href="/about">
<button>Go to About Page</button>
</Link>
のようにonClickpropが使えるものは何でも子要素にできる
Using Shared Components
この章でやること
共通Headerをつくって複数のページから利用する
Layout componentで複数のページのレイアウトを決める
componentsディレクトリにコンポーネントを作成していろんなページで読み込める
HeaderをつくったりLayoutをつくったりできる
ここまでで複数ページをどうつくるか理解できている
Create Dynamic Pages
ブログアプリで動的にページを作っていく例
モチベーション
ページを作るためにはディスクに実態をつくらないといけないが、動的なコンテンツを表示するために動的にページが作りたい時がある
方法:Next.jsではいくつか方法がある。query stringsを使うのからはじめる
<Link href={/post?title=${props.title}}>のようにqueryを指定できる
/postでpages/post.jsにpropsを渡すことができる
post.jsではwithRouter()の中ではprops.router.queryでクエリパラメータが取得できる
まだできないこと
/blog/lhello-nextjsのようなURLを与えたい
すべてのquery stringでレンダリングに必要な情報のすべてを渡す
Clean URLs with Route Masking
できること: 実際のURLではない URLをブラウザに表示する
これがhttp://localhost:3000/post?title=Hello%20Next.js
こうなるhttp://localhost:3000/p/hello-nextjs
asを使うとブラウザに示すURLを指定できる
<Link as={/p/${props.id}} href={/post?title=${props.title}}>
問題
実際にみているのはhello-nextjsではないので、その状態でリロードするとサーバにリクエストがとんで404になる
https://gyazo.com/09e7a7c83b41357d7f65c44244d69d98
解決策
この問題はcustom server APIを使うことで解決できる
Server Side Support for Clean URLs
custom server APIをつかって、前節の、リロード時に404になる問題を解決する
Expressでcustom serverをたてて設定を書く
/p/:idでアクセスされたらclient sideでレンダリングしたものと同じページを出すようにする
注意:npm run devをやりなおさないとserver.jsの内容は反映されない
とはいえQuery Stringでもらったような情報がもらえないので、内容が変わってしまう
https://gyazo.com/95a549396e8cb92293ca48774a4d8004
理由:リロードしたときのサーバへのリクエストにはタイトル情報は含まれないので、同じページが出せない
code:js
server.get('/p/:id', (req, res) => {
const actualPage = '/post'
const queryParams = { title: req.params.id } // 仕方なくtitleをidにしている
app.render(req, res, actualPage, queryParams)
})
現実に問題になることは少ない。理由
But in the real world, this won't be much of an issue because we'll use an ID to fetch data from a data server in both client and the server.
Fetching Data for Pages
外部のAPIをたたいてpagesにもってくるようなしくみを提供している
getInitialProps()を使うとページにAPI渡した結果のpropsをわたせる
server/clientどちらでも使える
直接アクセスした場合はserverでgetItinialProps()がよばれるし、client sideで遷移した場合にはclient sideでよばれる
code:server.js
server.get('/p/:id', (req, res) => {
const actualPage = '/post'
const queryParams = { id: req.params.id }
app.render(req, res, actualPage, queryParams) // serverがpageを呼んで、その中でinitializeされる
})
https://gyazo.com/9f864b486007a2ed003a5a95ba8cf2ff
nextにおけるfetchをもっと知りたいなら
Styling Components
Reactアプリ一般の方法
従来の方法(SASS, PostCSSなど)
様々な問題がある。特にSSRで
Next.jsでは非推奨
推奨
他にも方法がある
code:js
<style jsx>{`
// ここにCSSをかける
h1 { }
`}</style>
styleは子コンポーネントには適用されない
globalにstyleをあてたいときがある
例えばmarkdownを使うときとか
code:js
<div className="markdown">
<Markdown source={`
This is our blog post.
Yes. We can have a link(/link). ### This is a title
And here's the content.
`}/>
</div>
<style jsx global>{` // global scopeになった
// ここにstyleをかくと子コンポーネントの<Markdown>にもstyleがでてきようされる
'}</style>
prefixingとかvalidationはbabelの中で行われるので追加のオーバーヘッドはない Deploying a Next.js App
複数インスタンスを実行する
code:package.json
"scripts": {
"start": "next start -p $PORT"
}
PORT=8000 npm run startとかでポートを指定して複数実行できる
Export into a Static HTML App
next exportで/outにはかれる
HTMLのexporutを行うためには事前の設定が必要(この設定がすべてを司っている)
code:next.config.js
module.exports = {
exportPathMap: function () {
return {
'/': { page: '/' }
}
}
}
こうすると/がexportされて、ナビゲーションはClient sideで適切にJSがロードされる
課題:直接URLにacccessしても404になる
理由:表示されているようなHTMLのページはホストされていないから。clientが適切なJS(ページを表示するpost.js)をロードしているだけ
https://gyazo.com/dabe5e103f596024074d47cf9cd865fc
次のようなconfigを書くことによって直接アクセスが可能になる
code:next.config.js
// このページにアクセスされたら :{page: 'このページのJSに', query: {'このQueryを投げる'} }
'/p/hello-nextjs': {page: '/post', query: {title: 'Hello Next.js'}},
'/p/learn-nextjs': {page: '/post', query: {title: 'Learn Next.js is awesome'}},
'/p/deploy-nextjs': {page: '/post', query: {title: 'Deploy apps with Zeit'}}
この場合、設定にpageを追加してもbuildし直す必要はない(pageはすでbuildされているため)
この方法が使えないケース
デプロイ後にpagesをdynamicに生成したい場合
next startでnode上にホストするか、APIを使う