11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Next.jsAdvent Calendar 2019

Day 6

あのサイトを Next.js に載せてみる

Posted at

この記事は、 Next.js Advent Calendar 2019 の 6日目の記事です。

本日の記事は、気楽に読んでいただければ幸いです。

はじめに

React + Next.js + Firebase でのアプリケーション作成の素振りをしようとしていたところ、2年くらい前の「阿○寛のサイトが dev.to 並に早い」というネタを思い出していたこともあって、 React + Next.js で組み立て直してみようかとも思いましたが、2年前にPWA化までしていた記事もあったので、さらに昔を懐古して、あのサイトのテンプレで「前○プロフ」みたいなサイトを作ってみようと思った次第です。

出来上がった黒歴史プロフサイト

Screen Shot 2019-12-06 at 1.15.07.png

※上記サイトは、2019年のアドカレ期間終了後は落としているかもしれません。ご了承ください🙇‍♂️

ソースコードは ↓
https://github.com/uitspitss/ano-site

Next.js

今回、Next.js を使いこそはしましたが、React Hooks にいろんなものを押し込めることができたおかげで、Next.js に背負ってもらったのは、ユーザー情報ページへのルーティングとちょっとしたAPIくらいになってしまいました。

Dynamic Routing

ドキュメントはこちら → Next.js Documentation #Dynamic Routing

  1. server(Express)側も組み合わせた Dynamic Routing
  2. [id].js といったパラメーターページを使った Dynamic Routing

の2通りで書いたので、そのあたりの説明を書きたいと思います。

プロフサイトということでページ構成としては、/ 以降にユーザーID(今回は Twitter アカウントの Screen Name)ごとのページが存在する構成になります。
このユーザーIDごとのページを動的に生成するイメージのルーティングなので、その部分を Next.js にルーティングしてもらいます。

/ ┬─ john
  ├─ thomas
  ├─ julia
  ├─ [screenName]
  .
  .
  .

1. server(Express)側も組み合わせたDynamic Routing

↓server(Express)側のコード抜粋

src/functions/index.ts
server.get('/:screenName', (req: Request, res: Response) => {
  return app.render(req, res, '/', { screenName: req.params.screenName });
});

パスで指定した変数に入れて、ページコンポーネント側に渡してあげます。

↓ページコンポーネント側のコード抜粋

src/app/pages/index.tsx
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 };
};

getInitialPropsquery 内に渡ってくるので、ページコンポーネントに渡します。

デモ: https://ano-site.web.app/ano_site

2. [id].js といったパラメーターページを使った Dynamic Routing

server側は特にいじりません。

↓ページコンポーネント側のコード抜粋

src/app/pages/users/[screenName].tsx
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

公式ドキュメント以外の参考にした文献等

最後に

今回、Next.js + React + Firebase だけではなく、

  • Semantic UI React
  • Emotion
  • react-hook-form
  • i18next(next-i18next)

等々、人気のあるライブラリを触ってみたかったので、アプリケーションを仕立てました。
なので、 Next.js + React + Firebase の参考にでもなれば幸いです。

今月に入った頃から、Semantic-UIのアイコンが読み込めなくなって、原因を探ったり、 Font Awesome に切り替えたりしていたら、時間切れになってしまい、中途半端感ありありです。

ともあれ、このあたりで締めたいと思います。
ちょっと早い時期ですが、みなさま良いお年を〜

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?