この記事は、 Next.js Advent Calendar 2019 の 6日目の記事です。
本日の記事は、気楽に読んでいただければ幸いです。
はじめに
React + Next.js + Firebase でのアプリケーション作成の素振りをしようとしていたところ、2年くらい前の「阿○寛のサイトが dev.to 並に早い」というネタを思い出していたこともあって、 React + Next.js で組み立て直してみようかとも思いましたが、2年前にPWA化までしていた記事もあったので、さらに昔を懐古して、あのサイトのテンプレで「前○プロフ」みたいなサイトを作ってみようと思った次第です。
出来上がった黒歴史プロフサイト
※上記サイトは、2019年のアドカレ期間終了後は落としているかもしれません。ご了承ください🙇♂️
ソースコードは ↓
https://github.com/uitspitss/ano-site
Next.js
今回、Next.js を使いこそはしましたが、React Hooks にいろんなものを押し込めることができたおかげで、Next.js に背負ってもらったのは、ユーザー情報ページへのルーティングとちょっとしたAPIくらいになってしまいました。
Dynamic Routing
ドキュメントはこちら → Next.js Documentation #Dynamic Routing
- server(Express)側も組み合わせた Dynamic Routing
-
[id].js
といったパラメーターページを使った Dynamic Routing
の2通りで書いたので、そのあたりの説明を書きたいと思います。
プロフサイトということでページ構成としては、/
以降にユーザーID(今回は Twitter アカウントの Screen Name
)ごとのページが存在する構成になります。
このユーザーIDごとのページを動的に生成するイメージのルーティングなので、その部分を Next.js
にルーティングしてもらいます。
/ ┬─ john
├─ thomas
├─ julia
├─ [screenName]
.
.
.
1. server(Express)側も組み合わせたDynamic Routing
↓server(Express)側のコード抜粋
server.get('/:screenName', (req: Request, res: Response) => {
return app.render(req, res, '/', { screenName: req.params.screenName });
});
パスで指定した変数に入れて、ページコンポーネント側に渡してあげます。
↓ページコンポーネント側のコード抜粋
const IndexPage: NextPage<Props> = ({ screenName }) => {
const { user: twitterUser, timeline, loading: twitterLoading } = useTwitter(
screenName,
);
const { user: siteUser, loading: siteLoading } = useSiteUser(screenName);
return (
<>
<FirebaseApp>
<MainColumn
screenName={screenName}
siteUser={siteUser}
twitterUser={twitterUser}
timeline={timeline}
loading={twitterLoading || siteLoading}
/>
</FirebaseApp>
</>
);
};
IndexPage.getInitialProps = async ({ query }) => {
let screenName = query ? query.screenName : null;
screenName = screenName ? (screenName as string).split(', ')[0] : 'uitspitss';
return { screenName };
};
getInitialProps
で query
内に渡ってくるので、ページコンポーネントに渡します。
デモ: https://ano-site.web.app/ano_site
2. [id].js
といったパラメーターページを使った Dynamic Routing
server側は特にいじりません。
↓ページコンポーネント側のコード抜粋
const UserPage: NextPage = () => {
const router = useRouter();
let { screenName } = router.query;
screenName = screenName ? (screenName as string).split(', ')[0] : 'uitspitss';
const { user: twitterUser, timeline, loading: twitterLoading } = useTwitter(
screenName,
);
const { user: siteUser, loading: siteLoading } = useSiteUser(screenName);
return (
<>
<FirebaseApp>
<MainColumn
screenName={screenName}
siteUser={siteUser}
twitterUser={twitterUser}
timeline={timeline}
loading={twitterLoading || siteLoading}
/>
</FirebaseApp>
</>
);
};
useRouter
経由で screenName
を拾っています。ここは withRouter
のHOCを使うこともできるようです。
デモ: https://ano-site.web.app/users/ano_site
公式ドキュメント以外の参考にした文献等
-
りあクト! Firebaseで始めるサーバーレスReact開発
- React + Firebase のあたりはこの本とサンプルコードをとても参考にしてます。実践的な内容がまとまっていてとても良い本です。
-
実践TypeScript
- Next.js での TypeScript の扱いなど、こちらも実践的な内容が書かれている本です。
-
With Firebase Hosting and Typescript example
- Next.js の React + TypeScript + Next.js のサンプル。Next.jsのサンプル集は充実していて、今回作ったアプリケーションのような Firebase を組み合わせるケースや、semantic-ui と組み合わせるケースなど、様々なユースケースのサンプルが用意されています。
-
いまみているウェブページを阿部寛のサイトっぽくするChrome拡張を作った
- あのホームページの独特感の源である、背景の薄緑文字をCSSで再現する方法を参考にしました。
- 今回作ったアプリケーションでは、
src/app/components/CharctersPrintedBackground.tsx
というコンポーネントに実装しました。
-
阿部寛さんのホームページ
- 大変畏れ多いですが、ネタ元です。
最後に
今回、Next.js + React + Firebase だけではなく、
- Semantic UI React
- Emotion
- react-hook-form
- i18next(next-i18next)
等々、人気のあるライブラリを触ってみたかったので、アプリケーションを仕立てました。
なので、 Next.js + React + Firebase の参考にでもなれば幸いです。
今月に入った頃から、Semantic-UIのアイコンが読み込めなくなって、原因を探ったり、 Font Awesome に切り替えたりしていたら、時間切れになってしまい、中途半端感ありありです。
ともあれ、このあたりで締めたいと思います。
ちょっと早い時期ですが、みなさま良いお年を〜