Next.js + TypeScript + Emotionの開発序盤でつまづいたところ3点
概要
個人で、タイトルの環境でアプリをつくる際に、いくつかつまづいた箇所があったので、備忘録として残します。
環境
- next: 12.0.9
- react: 17.0.2
- typescript": 4.5.5
- emotion: 11.0.0
- @emotion/babel-plugin": 11.7.2
- @emotion/react": 11.7.1
- @emotion/styled: 11.6.0
1. 環境変数が読み込めない
dotenvは入れていたのですが、.env.developmentに設定した環境変数を読み込むことができず、はて?となりました。
これはそれぞれの環境変数のあたまにNEXT_PUBLIC_
をつけていなかったことが原因でした。Next.jsでは、クライアント側で環境変数を使いたい場合はこの接頭語をつけてあげる必要があるらしく、その対応により無事読み込まれるようになりました。
NEXT_PUBLIC_FIREBASE_API_KEY="hoge"
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN="fuga"
NEXT_PUBLIC_FIREBASE_PROJECT_ID="piyo"
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET="hogehoge"
NEXT_PUBLIC_FIREBASE_MESSAGE_SENDER_ID="fugafuga"
NEXT_PUBLIC_FIREBASE_APP_ID="piyopiyo"
こんな感じで。
しか私はFirebaseのinitializeの設定をするにあたり、以下のように環境変数を使用しており、このコードに対して、apiKeyが環境変数からちゃんと渡されていません(大略)
というエラーが出ていたわけですが、このコードって特にコンポーネントとか書いていないけどクライアント側としてみなされるの...?と少し疑問も持ちました。
import firebase from "firebase/compat/app"
import "firebase/compat/auth"
import "firebase/compat/firestore"
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGE_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
}
firebase.initializeApp(firebaseConfig)
export const auth = firebase.auth()
export default firebase
調べきれていないので断言はできませんが、おそらく、環境変数を使用した関数をクライアント側でimportする場合は、結局「クライアント側で環境変数を使用している」と認識されるのかなと思います。上記でexportしたfirebase
をimportしていたページでは、のきなみエラーが出ていたからです。
少し雑な話にはなりますが、とりあえずNext.jsを使ううえでは環境変数にはNEXT_PUBLIC_
をつけておくとまちがいないのかなと思います。
2. Emotionが使えない
普通にインストールしただけだと、CSS in JSライブラリであるEmotionを使うとエラーが出てきちゃいました。
それに対して、以下の記事を参考にさせていただき、対応しました。
やったことは2つです。
1. babelの設定をする
yarn add @emotion/babel-plugin
を実施し、その後トップディレクトリに.babelrcというファイルを作成して以下の設定を書いてあげればOKです。
{
"presets": [
[
"next/babel",
{
"preset-react": {
"runtime": "automatic",
"importSource": "@emotion/react"
}
}
]
],
"plugins": ["@emotion/babel-plugin"]
}
2. Emotionの型定義ファイルを読み込む
1をしてあげただけでも正常にCSSがページに反映されるようにはなるのですが、エディタからは引き続き怒られてしまいます。そのエラーはどうやらEmotionのtypesがうまく機能していないためのようなので、型定義ファイルを読み込ませます。
具体的には、トップディレクトリにadditional.d.ts
というファイルをつくり、そこに以下を書いてあげるとOKです。
/// <reference types="@emotion/react/types/css-prop" />
ファイル名はなんでもいいのですが、Next.jsにはもともとnext-env.d.tsという型定義ファイルがあり、そこに追加した形なのでadditionalです。
ちなみにnext-env.d.tsに直接このディレクティブを書くと、(私の環境では)ビルド時に勝手に消えちゃいます。
3. windowオブジェクトを使っているページをSSRできない
Next.jsにおいてサーバーサイドレンダリングをしているページでは、ブラウザでは使用可能なwindowオブジェクトを使用することができません。使っちゃうとWindow is not defined
と出ます。
私の場合は、直接windowオブジェクトを何処かで使用していたわけではないのですが、importしていたライブラリ内で使われていたようです。
要するに、サーバーサイドではなくクライアントサイドでレンダリングしてあげればいいので、以下の設定を加えました。
import dynamic from "next/dynamic"
// import元はレンダリング対象となる実質のコンポーネント
const DynamicComponent = dynamic(() => import("../src/components/editor"), {
ssr: false,
})
const Article = () => {
return <DynamicComponent />
}
export default Article
こうすることでSSR(サーバーサイドレンダリング)はオフになり、無事ページを表示することができました。
所感
こうしたところでつまづいたものの、Gatsby.jsなどとちがってNext.jsは、自分でルーティングの設定とかをしなくていいところに感動しました。
参考記事
Discussion