Next.jsでローカルではbuildできるけどvercel上でビルドエラーの対応

# はじめに
Vercelでサイトを作っていて、ローカルではbuildが通るのに、vercel上でbuild errorになって、なんとか解決できたのでその記録です。これに遭遇する人がどれだけいるかわかりませんが。

内容はあまり関係ないと思いますが、作っているのはいちおうこちら。

https://small-pieces.vercel.app/

NextやReactの勉強も兼ねている個人事業主としての自分のHPで、そういう理由のためソースは公開していないです。


# 起きたエラー
vercelで実行されるというコマンド`npm run build`について、
- ローカルでは、正常に実行できて、当然そのあと`npm run start`も正しく動く
- vercelでは、下記のエラーが出た
    - `TypeError: d(...).readdirSync(...).filter(...).map(...).toSorted is not a function`

先に結論を書いておくと、`toSorted()`を使わず、代わりに`sort()`へ置き換えたら通りました。それだけ。理由はわかっていません。

```
TypeError: d(...).readdirSync(...).filter(...).map(...).toSorted is not a function
    at i (/vercel/path0/.next/server/chunks/5463.js:8:6619)
    at Object.nF [as generateStaticParams] (/vercel/path0/.next/server/app/blog/[slug]/page.js:1:135233)
    at buildParams (/vercel/path0/node_modules/next/dist/build/utils.js:1026:58)
    at buildParams (/vercel/path0/node_modules/next/dist/build/utils.js:1020:28)
    at /vercel/path0/node_modules/next/dist/build/utils.js:1043:39
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.wrap (/vercel/path0/node_modules/next/dist/server/async-storage/static-generation-async-storage-wrapper.js:48:24)
    at buildAppStaticPaths (/vercel/path0/node_modules/next/dist/build/utils.js:981:85)
    at /vercel/path0/node_modules/next/dist/build/utils.js:1177:120
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
> Build error occurred
Error: Failed to collect page data for /blog/[slug]
    at /vercel/path0/node_modules/next/dist/build/utils.js:1268:15
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  type: 'Error'
```

`app/blog/[slug]/page.js`の中で使っている、`toSorted`がfunctionではないと言われているみたい。でもbuildされた後の行,列番号なので、どこなのかはっきりわからない。でも`toSorted()`のところなのかな。

## 環境
- バージョン
    - next@14.2.1
    - react@18.2.0
- ローカル環境
    - Windows10 Pro

## toSortedの実際のコード部分（対応前の状態）
```JavaScript:app/blog/[slug]/page.js(抜粋)
    // dateでソート
    const sortedBlogs = blogs.toSorted((a,b)=>{
        if (a.frontmatter.date < b.frontmatter.date){
            return -1*sortOrderVal;
        }
        return 1*sortOrderVal;
    }).map((b, i)=>{
        // ソートした結果に番号を振る
        return {
            ...b,
            i,
        };
    });
```
`blogs`を日付でソートしています。`toSorted`がないと言っているので、細かいところはおそらく関係ないので、あまり見なくてよいです。（なんかちょっと恥ずかしい:sweat_smile:）

`sort()`でなく`toSorted()`を使っているのは、そのままですが、`blogs`を変更したくないためです。

# 対策（対応後）
```JavaScript:app/blog/[slug]/page.js(抜粋)
    // dateでソート     // vercelでtoSorted()がNotFoundでエラーになるため、sortを利用
    const sortedBlogs0 = [...blogs];
    sortedBlogs0.sort((a,b)=>{
        if (a.frontmatter.date < b.frontmatter.date){
            return -1*sortOrderVal;
        }
        return 1*sortOrderVal;
    });
    const sortedBlogs = sortedBlogs0.map((b, i)=>{
        // ソートした結果に番号を振る
        return {
            ...b,
            i,
        };
    });
```
`sortedBlogs0`は、やっつけ感がある変数名ですが、細かいところはお気になさらず。`sort()`や`map()`の中身は、コピーしただけなのでまったく変更なし。

これでコンパイルが通って、正常に作動しました。

## 考えていたこと
エラーが出た時点の私の所感は、２つでした。

node_moduleの中の何かの問題（例えばOS違いの問題とか、モジュール同士の相性問題）だったら嫌だなぁということ。エラーメッセージの中で、`d(...).readdirSync(...).filter(...).map(...).toSorted`の、`toSorted`より左の関数たちはここで使っていないので、これは自分のコードではないのではって思っちゃいました。結果的には、最適化されてここに集まってたか。

もう１つは、ローカルでは正常終了なのでtypo的なものではないだろうなということ。

今振り返ると、どちらも「自分は正しい」という偉そうな感じがありますね。そういう気持ちがあると、バグとかミスとかに気づきにくくなるし、試行錯誤をあまりトライしなくなります。反省。

# まとめ
個人的には納得できていませんが、しばらく試行錯誤してなんとか回避はできたようなので、まぁいいか。自分が忘れたころにまた躓いたり、誰かがぶつかってここに流れ着いた人のために記録しておきます。:pencil2:
わかる方がいらしたら是非教えてください。

それにしてもローカルでは通るけどvercelでのビルドエラーはつらいなぁ。ググってみると、他にも起こるケースがあるようです。

ではよいNext.js with vercelライフを！