Open12

Reactでアプリを作成する際のメモ

とのこっことのこっこ

"npm run dev"でのテスト時にHydrationエラーが発生。
文言を見てみると下記が悪さをしているみたい。

data-google-analytics-opt-out=""

シークレットタブで開くとエラーが出なくなったので、Chromeの拡張機能が悪さをして居たっぽい。
実害はないはずなので無視。

参考サイト

https://zenn.dev/maito/articles/b5009dd3c558a1

とのこっことのこっこ

Next.jsプロジェクトをFirebase Hostingで公開する

なんか静的ファイルが直接作成されないので、
Firebase FunctionsでNext.jsとReactでDOMの作成
→「作成されたDOMをHosting」という手順が必要そう
もっと簡単な方法がある気がする!!

  1. firebase.jsonの更新
{
  "hosting": {
    "public": ".next",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "function": "nextjs"
      }
    ]
  },
  "functions": {
    "source": "functions",
    "runtime": "nodejs18"
  }
}
  1. functionsフォルダをプロジェクト直下に作成(firebase.jsonと同じフォルダ)

https://qiita.com/toshiaki_takase/items/ce65cd5582a80917b52f
https://zenn.dev/gladevise/articles/nextjs-firebase-hosting

とのこっことのこっこ

Next.jsプロジェクトをFirebase Hostingで公開する

クライアント側で完結するなら圧倒的にこっちの方法がいい。
Functions使う方はうまくいかなかった

前回

Firebase側でFunctions機能を使用してビルドして描画

今回

ローカルで静的ファイルをビルドしてHosting

  1. next.config.jsにexportを追加
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
  output: 'export',// ←ここ
};

export default nextConfig;

注意 next export コマンドが紹介されている記事がいくつかヒットしたが、最近は使えなくなったらしい。

  1. ビルド
    自動でoutフォルダに静的ファイルが作成される。
npm run build
  1. firebase.json を修正
    デフォルト設定の場合「public:"public"」になっているので、ビルド結果が保存される"out"に変更。
{
  "hosting": {
    "public": "out",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
  }
}
  1. ホスティング
    別途プロジェクトの作成やfirebaseへのログインは必要
firebase deploy --only hosting

参考サイト

https://qiita.com/takiguchi-yu/items/5d22048b578bd311b996

とのこっことのこっこ

ReactでFirebaseを使う

  1. firebaseでwebアプリを追加
    プロジェクトは作成済みの前提。
    プロジェクトトップから「アプリを追加」でwebアプリを選べばOK

  2. firebaseをinstall

npm install firebase
  1. コード内に初期設定をコピペ
    コピペするコードが表示されるので、そのままコピーする。
    プロジェクトやユーザーごとに異なる値になるはず。
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "your_apiKey",
  authDomain: "your_authDomain",
  projectId: "your_projectId",
  storageBucket: "your_storageBucket",
  messagingSenderId: "your_messagingSenderId",
  appId: "your_appId",
  measurementId: "your_measurementId"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
とのこっことのこっこ

ReactアプリをFirebase Hostingで公開する

静的サイトの公開はできたが、サーバーサイドでの動的な処理が実現できない。
具体的にはApp routerを使ったページ処理ができなかったので、対応方法を考える。

方針

一応Next.js用にバックエンドも統合したFirebaseの設定を作成する方法があるらしい。
ただし、プレビュー機能なので消滅する危険性あり。
https://firebase.google.com/docs/hosting/frameworks/nextjs?hl=ja

  1. Firebase CLI で、ウェブ フレームワークのプレビューを有効化
firebase experiments:enable webframeworks
  1. Firebase Hostingの初期化
firebase init hosting
  1. firebaseのダウングレード
    不要な人もいるはずだが、おそらくサーバー側のNext.jsの依存関係の影響でダウングレードが必要だった。
npm install firebase@10.14.1

参考

firebase init を実行した際は次のような質問をされた。

? Detected an existing Next.js codebase in the current directory, should we use this? (Y/n) 

→ Next.jsのコードがあるけどこれを使う? と聞かれています。
さきほど作成したNext.jsのプロジェクトを使うので「Yes」でいきます。


? In which region would you like to host server-side content, if applicable?
> us-central1 (Iowa)
  us-east1 (South Carolina)
  us-west1 (Oregon)
  asia-east1 (Taiwan)
  europe-west1 (Belgium)

→ サーバーの場所を選べるようになっていました。前やった時はこんな親切じゃなかったような……。
どこでもいいですが、とりあえず日本に近い台湾(asia-east1)を選びます。

今後の対応

Firebase App Hostingを「強く」推奨しているらしいので、移管する
https://firebase.google.com/docs/app-hosting?hl=ja

とのこっことのこっこ

Twitterカードを表示させたい

やったこと

  • react-helmetを使えばいいのか?
    → ビルドに成功しない。そもそもメンテナンスされてなくない?

  • react-helmet-asyncならビルド通るじゃん!
    → twitterカードが表示されない。

  • なるほど、next/headってやつでサーバーサイドでmeta-dataを記述すればいいんやな
    → 失敗。metadataがhtmlにない……。

成功例

App routerを使っている場合は方法が違うらしい。
次のように、metadataをexportすれば自動でheadにmetadataを追加してくれるようになったらしい。

// layout.tsxやpage.tsx内
import type { Metadata } from "next";
export const metadata: Metadata = {
  title: "タイトル",
  description: "説明,
  openGraph: {
    title: "タイトル",
    description: "説明",
    url: "https://yourdomain.com",
    images: [
      {
        url: "画像パス",
        width: 1200,
        height: 630,
        alt: "alt",
      },
    ],
  },
  twitter: {
    card: "summary_large_image",
    title: "タイトル",
    description: "説明",
    images: ["画像パス"],
  },
};

参考サイト

https://zenn.dev/salesnow_tech/articles/0c7aac95563506
https://nextjs.org/docs/app/building-your-application/optimizing/metadata

カードタイプで表示できているかはこちら↓で確認

https://cards-dev.twitter.com/validator

とのこっことのこっこ

Firestoreのアクセス権を設定する

基本は公式ドキュメント
https://firebase.google.com/docs/firestore/security/get-started?hl=ja

ちゃんとアクセス制限するにはFirebaseだとApp Checkを使うのが良いかも

App Check

基本

ちょっと画面が変わっているが、次のサイトが参考になった。
https://qiita.com/yuta-katayama-23/items/e071e167caef2e2f780e

料金

スケールを大きくするためにはEnterpriseがいいかも。
無料枠はある。
https://cloud.google.com/recaptcha/docs/compare-tiers?authuser=0

無料にこだわるなら……

Authenticationの「匿名認証」を使うのが楽かも。

匿名認証の設定手順

すぐ変更になるので、参考までに

  1. Firebase コンソールにアクセス。
  2. 左側のメニューから「Authentication」を選択。
  3. 上部の「ログイン方法」タブをクリック。
  4. 「匿名」プロバイダを有効にする。

匿名認証を実装

コード例

import { initializeApp } from 'firebase/app';
import { getAuth, signInAnonymously } from 'firebase/auth';

// Firebase プロジェクトの設定
const firebaseConfig = {
  apiKey: 'YOUR_API_KEY',
  authDomain: 'YOUR_PROJECT.firebaseapp.com',
  projectId: 'YOUR_PROJECT_ID',
  storageBucket: 'YOUR_PROJECT.appspot.com',
  messagingSenderId: 'YOUR_SENDER_ID',
  appId: 'YOUR_APP_ID',
};

// Firebase アプリの初期化
const app = initializeApp(firebaseConfig);

// Firebase Authentication の初期化
const auth = getAuth(app);

// 匿名認証を行う関数
export const signInAnonymouslyToFirebase = async () => {
  try {
    await signInAnonymously(auth);
    console.log('匿名認証に成功しました');
  } catch (error) {
    console.error('匿名認証に失敗しました', error);
  }
};

Firestoreのルールを設定する

ルール例

service cloud.firestore {
  match /databases/{database}/documents {
    
    // fortune コレクションのルール
    match /myCollection/{documentId} {
      allow read, write: if request.auth != null;
    }
  }
}
とのこっことのこっこ

Google AdSensの追加

App routerを使用しているなら、Metadataに追加するのがベターな気がする。
AdSense用のプロパティはないようなので、otherプロパティに追加すればちゃんと認識された。

import type { Metadata } from "next";

const URL_BASE = "https://bubblepopper.click";
export const metadata: Metadata = {
  title: "title",
  other: {
    "google-adsense-account": "AdSens登録時に表示されるmetadataのcontent部分",
  },
};
とのこっことのこっこ

Firebase設定メモ

次のコマンド実行時の選択肢

firebase init
then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert       
selection, and <enter> to proceed)

( ) Data Connect: Set up a Firebase Data Connect service
( ) Firestore: Configure security rules and indexes files for Firestore
( ) Genkit: Setup a new Genkit project with Firebase
( ) Functions: Configure a Cloud Functions directory and its files
( ) App Hosting: Configure an apphosting.yaml file for App Hosting
( ) Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
( ) Storage: Configure a security rules file for Cloud Storage
( ) Emulators: Set up local emulators for Firebase products
( ) Remote Config: Configure a template file for Remote Config
( ) Extensions: Set up an empty Extensions manifest
( ) Realtime Database: Configure a security rules file for Realtime Database and (optionally)       
provision default instance

→ 笑っちゃうくらい選択肢がでてきました……。
とりあえず、ミニマムな構成でホスティングを行いたいので「Hosting」に合わせて「スペース」ボタンを押した後に「エンター」を入力します。