Open19

pages routerをapp routerへ移行していく

takky94takky94

componentは100くらい、pageのファイルが30くらいの規模感
pages内を全部appへ向けて雑に放り込んだら見事にぶっ壊れたので多少丁寧にやっていくしかなさそう

takky94takky94

componentも一旦appに突っ込んで全てにuse clientをつけた
幸い(?)、今までSCを全く使ってなかったのでひとまず全てをCCとして扱って良さそう
pages/内ファイルを1つずつ真心込めてapp/に投げ込んでく
そんでapp/に放り込んだページからは@app/componentsを使用するようにすることでpages側とは切り離せた環境での移行作業ができる
@app/componentsは後で@/componentsと融合させていく

memo: 全部終わったらlayout.tsxやpage.tsxに合わせて各コンポーネントをキャメルからケバブで命名振り直したい

takky94takky94

同僚に聞きたいことメモ

  1. next/routerrouter.push('hoge', undefined, {scroll: false})next/navigationではどのように行うか(スクロールさせずに遷移)
  2. next/router
    router.push({
      pathname,
      query: { ...query, hoge: newHoge },
    })

みたいなコードの置換方法(クエリパラメータゴリゴリ使ってるページ等から呼び出されて、既存のクエリパラメータを引き継ぎつつ、特定のクエリパラメータのみを更新するようなcomponentで使用してる)

takky94takky94

_app.tsxのProviderをCCでラップ

Provider類が軒並みuseState等使用してるので

// providers.tsx
"use client"

export default function Providers({children}: {chidren: React.ReactNode}){
  return (
    <HogeProvider>
      <FugaProvider>
        {children}
      </FugaProvider>
    </HogeProvider>
  )
}

とprovider群をラップしたcomponent作ってRootLayoutに追加した

takky94takky94
Error: Conflicting app and page file found: "src/app/hoge/[id]/page.tsx" and "src/pages/hoge/[id].tsx". Please remove one to continue.

app/とpages/とで重複パスによるエラー
pages/側削除済でも上記みたいなエラー起こりがち
localサーバー再起動で解消する

takky94takky94
src
├── components
├── pages
├── styles
└── types

みたい構成好きだったけど、コロケーションに沿うなら

app/hoge
├── _components
├── style.module.scss
├── page.tsx
└── type.ts

みたいにした方がいいのかな

cssもここら辺置くならもう

 _components/hoge
├── index.tsx
├── style.module.scss
├── index.stories.tsx
└── type.ts

こういう構成で良さそう

takky94takky94

なんかこのCC/SCの感じ、既視感あるなぁと思ってたらアイランドアーキテクチャか

takky94takky94

Error: NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted

この手のは大体next/routerをnext/navigationに置き換えれば解決する(雑)

takky94takky94
router.asPath
       ^^^^^^

この手の型エラーは大体next/routerをnext/navigationのusePathnameに置き換えれば解決する(雑)

takky94takky94

usePathname、なんでnullも返り値になり得るのかと思ったら

  /**
   * If the hook is accessed from `pages/`, the pathname may be `null` when the
   * router is not ready.
   */

らしい

takky94takky94

typedRoutes 有効にすると pathname() + クエリパラメータ とかに飛ばしたい時にエラー出てしまうな

takky94takky94

app router対応済みのexample見ると

page.tsx
_components/HogeFuga.tsx

みたいにキャメルとケバブ混在ケースもあるんだな

ref:https://github.com/vercel/next.js/tree/canary/examples/with-redux/app

もちろん

page.tsx
_components/hoge-fuga.tsx

みたいにケバブ統一してるケースもある

ref:https://github.com/vercel/next.js/tree/canary/examples/app-dir-i18n-routing

キャメル慣れちゃっていつの間にか嫌悪感なくなってたけど視認性考えると圧倒的にケバブ統一の方が良い気がする

takky94takky94

componentもpageやloaderなどに合わせて小文字に統一することにした
gitはデフォではファイル名の大文字小文字の差分を検知しないのでvim .git/config

[core]
-        ignorecase = true
+        ignorecase = false

とし、ファイル名の差分を追跡するようにした
ただ、historyは消し飛ぶので注意が必要
ちゃんと歴史を残したければ機械的にgit mvを実行するシェルスクリプトとか組めば良さそう(今回は面倒なのでignorecaseでサクッと終わらせる)
一旦一括削除してcommit、復元してrename後にcommitでも多分残るはず

いまのフロントエンドではファイル名がそのままルーティングになるfwが多いから、ファイル名の変更は意味のある差分だと思うしここら辺もう少しスマートな仕組みが欲しいなとは思う


ignorecaseでは意図した通りに動かない部分があったので

#!/bin/bash

find app/_components -type f -name '*.tsx' | while read file; do
  if [[ $(basename "$file") =~ [A-Z] ]]; then
    git mv "$file" "$file.tmp"
    git mv "$file.tmp" "$(echo "$file" | tr '[:upper:]' '[:lower:]')"
  fi
done

これを実行したら大文字小文字の置き換えが完了した(chat gptに作ってもらった)

takky94takky94

それなりにボリュームがあるからccからscを呼び出してしまった時にどこ起因であるかの特定が地味に面倒

takky94takky94
  • _components/client, _components/serverみたいに分離させる
  • component名でCCかSCかを明示的にする

でストレスちょっと減りそう
<Modal /> => <CCModal />

takky94takky94

ルーティングのグループのカッコと動的パスのブラケットのおかげでcmd+clickのジャンプが最高にやりづらくなってしまった問題