nextjs を掘る
とりあえずドキュメントを一読して、気になるところがあればコメントしていく
読み始めた時の nextjs の version 10.2
更新されればこのリリースノートを読めばよさそう。
https://github.com/vercel/next.js/tree/canary/examples オフィシャルのボイラープレート集。パッケージを入れたい時などは参考になる。
雑にまとめると
/pages に react のコンポーネントをページ名のファイルで宣言して default export で宣言すればいい感じにマッピングしてくれる
/public においておけば静的なファイルサーバーとしてホスティングしてくれる マッピングは /
以上, webpack とか express とかで一から構築すること比較すると楽すぎて泣けてくる
ダイナミックルーティング
例えば商品ページなら /pages/goods/[goodsID].tsx
とかでダイナミックルーティングしてくれる
プリレンダリングについて、いきなり肝の部分きた!
- SSG と SSR できる レコメンドは SSG (まあ、そっちの方が比較的早いしキャッシュ効くしね...)
Importantly, Next.js lets you choose which pre-rendering form you'd like to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others.
これはなかなかにスーパー機能... 商品ページは SSR, そんなダイナミックでないページは SSG って感じで使い分ければ、SSG のページは爆速いけそう。SSR は最適化次第か
SSG
Scenario 1: Your page content depends on external data
export async function getStaticProps
これはビルド時に呼び出される、従って SSG になる。
Scenario 2: Your page paths depend on external data
export async function getStaticPaths
これのコールバックが export async function getStaticProps({{params}}
になる
ユーザーの要求によって、ページにレンダリングする内容が異なるか、否かがSSG の使い所、
もし、ユーザーのリクエストに応じてページを変えたい場合は二つの選択肢がある。
CSR するか SSR するか。
- CSR 普通に ブラウザで非同期にリクエスト飛ばせばよい, SEO 問題 => これも2021 においては解消されてるか??、ユーザーの CPU パワーに速度が依存するのがデメリットかもだが、今時の端末ならそんな心配はいらないか...)
- SSR はキャッシュできない. (というか、逆にキャッシュできるのならば、そもそも SSR にしてるのはおかしい。リアルタイムにしたい場合は、ユーザー依存の場合は CSR でよさそう。SEO 関係ないし)
SSR
getServerSideProps()
のコールバックが export default const Page = ({data})
なだけ。
getStatic なら SSG getServer なら SSR で自動でビルド時に判別してくれるフレームワークっぽいところはこれだけ。めっちゃシンプルや!
所感
ほとんど SSGでできそう。ただし例えば EC とかの場合 トップ、商品詳細 は SSR がよさそう。SEO クソ大事でリアルタム性がシビアだと思うので, ページそのものをキャッシュさせるのは危ない。検索結果とかは CSR でいいと思うが、SEOに懸念がある場合はページ内遷移でない場合だけ SSR でそのほかは SPA 的に CSR させればよさそう。
ISR の解説がないけど、別ページか?
next メソッドは 型をくれるっぽい!最高!(まあ当たり前か...)
import { GetStaticProps } from 'next'
import { InferGetStaticPropsType } from 'next'
Incremental Static Regeneration
ISR きた!
next 9.5 から入った機能でわりと最近だった。
この機能は要は、バッチ処理のすごいやつ(多分)
着想としては ブラウザの Cache Controlにおけるstale-while-revalidateg らしい、
これは定期間をキャッシュからレスポンスするが指定時間を経過したら非同期でオリジナルをfetchしてキャッシュをレスポンス/更新するというもの。らしい。
これは CDN によっては対応してたりしなかったりするらしい... ソースを確かめてはないが、ブログれべるでは fastly Cloudflare は対応, clond front は対応してないとのこと
一定間隔でバックグラウンドでページを静的に生成して、動的なコンテンツもユーザーにはスタティックなサイト(早い)をとして見せる
revalidate
でその間隔は seconds で指定できる
どこまで極限までサイトを早くしたいんだ(呆れ)
ISR https://qiita.com/thesugar/items/47ec3d243d00ddd0b4ed
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every second
revalidate: 1, // In seconds
}
}
この秒間をどうやって決めるか、もちろんコンテンツの更新頻度に依存し増だが、どのユーザーはページを見てる時にはデータは切り替わらないのだから 60 秒とかでいいよな気もする。この間隔を狭めると計算リソースをもちろん使うので、負荷との兼ね合いでもあるか。
以下 ISR について理解を助ける記事
以下ISR のインフラに関する日本語記事 しかし.今のところ vercel 以外では ISR させるのはキツそう...
serverless-next.js ならば lamda@edge でいけるらしい... しかし、これは沼の可能性が高そう。
メソッドが詳しく解説されてる。preview モードとかあるのはよい。
https://swr.vercel.app/ の宣伝。まあSWR でよさそう
Reading files: Use process.cwd()
ファイルシステムにも普通に node の api で呼べる。
例えば md で管理してるものを html で描画したい場合などに使うっぽい
そのほかは普通に node でモジュールとして呼べばいいと思うので、乱用厳禁そう
export async function getServerSideProps(context) {
基本ここはがサーバーのエントリーポイントになる。いわゆるサーバーサイドの実装になる部分。
param, req, res, query, preview, locales 諸々必要なものが引数に入っている
バックエンドにサーバーがあるならあまりここでドメインロジックを書くのはやめたほうがよさそう。(書きたくなりそうだけど...)
所感
ここのページは nextjs の一番根幹のところだから、繰り返し読みたい
CSS について
グローバルにスタイルをおきたい場合は、以下のファイルに記述(cssmoduel としてインポート)
pages/_app.js.
Sass は普通にパケージを入れて .scss にすればサポートされる
CSSModule は ビルトインでサポートされている [name].module.css をファイル名にすれば css module として、クラスメイは hash がつく(ユニーク性が担保される) カスケーディングは同じファイル間であれば聞くと思われる (たぶん)
他に CSS in JS 系のライブラリの使い方はドキュメントにある Styled JSX は vercel 製なので推してくるが、使ってるところを見たことがないので CSS in JS を使う場合は
postcss は設定ファイルを弄る必要がありそう、アドバンスド機能でまた掘る
所感
採用したい CSS の記法次第で何にでも対応できそう。この辺僕はあんまり詳しくないけど、nextjs 的には css module 推奨っぽいので postcss でよさそう
画像最適化の機能
WebP に対応してるブラウザからのリクエストなら webp にして返す、デバイスごとに適切なサイズの画像を返す (sp に巨大画像を送らない)などが可能になる機能がある
API としては イメージタグの拡張として提供される
import Image from 'next/image'
function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src="/me.png"
alt="Picture of the author"
width={500}
height={500}
/>
<p>Welcome to my homepage!</p>
</>
)
}
export default Home
画像が別ドメインから配信されてる場合は
next.config.js に以下を指定すれば OK
module.exports = {
images: {
domains: ['example.com'],
},
}
画像を CDN においている場合は以下
module.exports = {
images: {
loader: 'imgix',
path: 'https://example.com/myaccount/',
},
}
imgx, cloudinary, akamai あたりはサポートしてるっぽい
これは CDN の挙動に応じて色々抽象化してくれるのだろうか...
あとビルドの時に width height で渡した値にリサイズしてくれるのだろうか? たぶんするのでは...
普通にファイルサーバーとして使える。pages でビルドされるであろうファイルと競合するファイル名はだめ
インクリメンタルビルドのすごい版についての解説、これのおかげでめちゃくちゃビルドの反映が早くて助かる
ビルドで困ったら詳しく読めばよさそう
提供されてる API には全部型があるっぽい、わからなくなったらここを見ればよさそう
dotenv がビルトインで入ってるっぽい
Next.js allows you to set defaults in .env (all environments), .env.development (development environment), and .env.production (production environment).
普通の node と同じくここで指定したファイルが process.env で読める
ちゃんと ie11 も対応してるよ!!😁
サーバーで fetch が使えるのは node-fetch が入ってるからっぽい
基本はデフォルトでいい感じにしてくれるが babel の設定を直接いじることも可能ではある
ルーティングについて
pages/blog/index.js → /blog
pages/blog/first-post.js → /blog/first-post
pages/dashboard/settings/username.js → /dashboard/settings/username
pages/blog/[slug].js → /blog/:slug (/blog/hello-world)
pages/[username]/settings.js → /:username/settings (/foo/settings)
pages/post/[...all].js → /post/* (/post/2020/id/title)
docker イメージある
環境変数やトークン入れる、クライアントなら JWT とかで良い気がする。
-
クッキーセッションライブラリはこれはよさそう
https://github.com/vvo/next-iron-session -
nextauth とかを使えば slack 認証とかもできるっぽい
1time token とかをリンクにもできそう
postcss.config.js で設定を拡張できる
module.exports = {
plugins:
process.env.NODE_ENV === 'production'
? [
'postcss-flexbugs-fixes',
[
'postcss-preset-env',
{
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
features: {
'custom-properties': false,
},
},
],
]
: [
// No transformations in development
],
}
全ページに export default PageName() に渡す前の制御をすべて定義できる
グローバル CSS もここで読む
_app.js が nextjs のグローバルエントリーポイント、_document.js は マークアップのグローバルエントリーポイント?という理解であってるか??
以下がデフォルト getInitialProps というやつがこのクラスコンポーネントには生えていてる
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
わかりやすかった。
要はライフサイクルに影響を及ぼしたりデータフェッチを用いるものを _app.js
エレメントにちょちょっと変更を加える倍は _docuemnt.js
404 , 500 系のページ宣言方法 やエラーが起こった際のページ
src 下にソースを掘れるらしい!これはうれしい。設定ファイル類は当然対象外、また publick フォルダもだめらしい
WebVitals を計測する reportWebVitals というメソッドが生えてる!
デバッグについて、デバッグで絶望したら詳しく読む
What is this inspired by? は面白いかった
このファイルはまあ巨大になりそう。
一応 webpack をフル拡張できるみたい。まあ、深い理由がない限り next に乗ってない機能をゴリゴリ使うのはどうかと思うが
gzip 圧縮はデフォルトで入っているが、無効にもできる