Next.jsのgetServerSideProps
やgetStaticProps
とJSON
Next.jsでSSRやSSRをする際に使うgetServerSideProps
やgetStaticProps
では、戻り値をJSONでシリアライズ可能な型に制限しなくてはならない制約があります。例えばデータベースから取得したデータがDate型を含む場合はエラーになってしまいます。
-
getStaticProps
でMongoDBデータベースから取得したデータがDate
型の値を含む場合:
export const getStaticProps:GetStaticProps = async (ctx) => {
const client = await new MongoClient("mongodb://127.0.0.1:27017");
await client.connect();
const db = client.db("DATABASE");
const col = db.collection("COLLECTION");
const posts = await col.find({}).toArray(); #created_atなどDate型を含んでいるとする
return {
props:{
posts
}
}
}
エラー
Server Error
Error: Error serializing `.data[0].date` returned from `getStaticProps` in "/".
Reason: `object` ("[object Date]") cannot be serialized as JSON. Please only return JSON serializable data types.
This error happened while generating the page. Any console logs will be displayed in the terminal window.
-
undefined
を含む場合:
コード
export const getStaticProps:GetStaticProps = async (ctx) => {
return {
props:{
data: undefined
}
}
}
エラー
Server Error
Error: Error serializing `.data` returned from `getStaticProps` in "/".
Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.
This error happened while generating the page. Any console logs will be displayed in the terminal window.
これを回避するためには、Date型をString型に変換するなど、JSONとしてシリアライズ可能な形式に変換する必要がありますが、毎回変換処理を書くのは面倒です。
こんなときに便利なライブラリがSuperJSONです。SuperJSONとNext.js用のBabelプラグインを使えば明示的な変換なしにgetServerSideProps
やgetStaticProps
でJSON範囲外のDate型などが扱えます。
- blitz-js/superjson
- blitz-js/babel-plugin-superjson-next: Next.jsで特別な記述なしにSuperJSONを使うためのbabel plugin
Next.js 12以降でのSuperJSON
しかしながらNext.js 12では標準のトランスパイラがBabelからSWCに変更され、blitz-js/babel-plugin-superjson-nextが標準では使えなくなりました。
SWC以降のNext.jsでもこれまでと同じようにSuperJSONを使えるようにしたのが、2021年12月に登場したremorses/next-superjsonです。
インストール
npm install superjson (未インストールの人)
npm install next-superjson
設定
next.config.js
にnext-superjson
用の設定を追加します。
const { withSuperjson } = require('next-superjson')
module.exports = withSuperjson()({
reactStrictMode: true,
})
アプリ側の処理
特に何も記述する必要はありません。SuperJSONを使わない場合はシリアライズが必要ですが自動でシリアライズしてくれます。
注意
- SuperJSONがSWC対応してくれるのが望ましいですが、未対応のためワークアラウンドとして使っています。将来SuperJSONがSWCに対応したらそちらに移行しましょう。
- 楽だからといってデータベースから取得したデータをNext.jsにそのまま投げるのはやめましょう。