UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Next.js】Next13で<html lang={locale}>を設定したい

Next.js 13で<html lang={locale}>を設定したい

Next.js 13以前ではpages/_document.jsで設定するが、Next.js 13 にはpages/_document.jsがなくなるため調べた

Next.js 13以前
nextjs.org

ドキュメントによるとNext.js 13での必須ファイルapp/layout.tsx(ルートレイアウト)でやるべきみたい

Next.js 13以降   beta.nextjs.org

ルートレイアウトは必須で、ここでhtmlタグやbodyタグを記載する

もし、headのtitleなどを動的に作りたい場合は、head.jsというファイルをページディレクトリの下に作るとページごとに動的に変わるtitleなどを設定することができる

app/blog/[slug]/head.tsx

export default function Head({ params }: { params: { slug: string } }) {
  return (
    <>
      <title>My Page</title>
    </>
  );
}

また、以下のようにルートグループと呼ばれるもの(フォルダ名を()で囲まれたフォルダ)をつくると、その下にそのグループ専用のlayoutファイルをつくることができる

ルートレイアウトはデフォルトでサーバーコンポーネントのため、クライアントコンポーネントに設定することはできない

逆にいうと初期描画時にはmetaタグなどが設定されている状態ということなのでSEO的には安心できる

【Next.js】SSR中にデータをフェッチしたものでreduxのstoreを初期化する

Next.jsにReduxを導入するとき、SSR中にデータをフェッチしたデータでreduxのstoreを初期化したい

どのページでも毎回やりたいことなので_app.tsxgetInitialPropsの中で行う

getInitialPropsはサーバー上で実行される

この中で、データフェッチを行いstoreを初期化する

MyApp.getInitialProps = async (appContext: AppContext) => {
  const appProps = await App.getInitialProps(appContext);
  const ctx = appContext.ctx;
  const reduxStore = initialiseStore({});
  const { dispatch } = reduxStore;
  const res = await fetch('/path/to/api/endpoint/');
  const json = await res.json();
  await dispatch(setData(json));

  appProps.pageProps = {
    ...appProps.pageProps,
    initialReduxState: reduxStore.getState(),
  };
  return appProps;
};

そして、MyAppコンポーネントでstoreを受け取り、Providerにセットすることで初期化が完了する

function MyApp({ Component, pageProps }: AppProps) {
  const reduxStore = createStore(pageProps.initialReduxState);
  return (
      <Provider store={reduxStore}>
          <Component {...pageProps} />
      </Provider>
  );
}

参考

www.quintessential.gr

【Next.js】ビルドするとFirebase Admin SDK でCan't resolve 'child_process' というエラーが発生する

Next.js に既存のReactアプリを移植してみたらビルド時にFirebase Admin SDK で次のエラーが発生した

error - ./node_modules/gcs-resumable-upload/node_modules/google-auth-library/build/src/auth/googleauth.js:xxx:0
Module not found: Can't resolve 'child_process'

調べると、Firebase Admin SDKはサーバーサイドで利用するモジュールにもかかわらず、フロントエンド側で呼び出していることが原因だとわかった

なので、getServerSidePropsapi内で使用するように修正した

解決に時間がかかったのは

next.config.jsでモック化(空オブジェクト)にすれば動く

などの情報を目にしてしまい、対処していたら次に

Module not found: Can't resolve 'fs'

が発生して、しばらくいたちごっこになってしまっていたため

冷静に考えればNode.jsのモジュールであることに気づけたので気をつけたい

【Next.js】titleタグに変数を渡すと警告が出る

Next.js でtitleタグに以下のように変数を渡していたら

  <title>{title} | My Company</title>

次のような警告がでた

Warning: A title element received an array with more than 1 element as children. In browsers title Elements can only have Text Nodes as children. If the children being rendered output more than a single text node in aggregate the browser will display markup and comments as text in the title and hydration will likely fail and fall back to client rendering

title要素が複数の要素を子として持つ配列を受け取ったと書いてあるが、検討がつかなかったのでなんだろうと調べたところ以下で解説されていた

github.com

このような書き方をした場合、

const Home: NextPage = () => {
  const world = "World";
  return (
    <div>
      <span>Hello {world} foo</span>
    </div>
  );
};

次のようにレンダリングされる

<div><span>Hello <!-- -->World<!-- --> foo</span></div>

spanの子要素は0だが、nodeとしてはtextcommenttextcommenttextの5つある

つまり、titleタグの実装もこのようになっていることになる

警告をよくよくみるとタイトル要素は1つのテキストノードしか持てないとあるので、以下のように書き換えればよいことがわかった

  <title>{`${title} | My Company`}</title>

【Next.js】React18にあげたらgoogle-map-reactでエラーが発生した

Next.js 13で既存のアプリを動かしてみたらgoogle-map-reactで次のようなエラーが発生した

Next.js: TypeError: Cannot read properties of undefined (reading 'getChildren')

以下のISSUEによるとNext.jsというより、React@18とのバージョン互換性の問題みたい

github.com

超暫定的な対応としてはnext.config.jsreactStrictMode: falseにすると動くが

const nextConfig = {
  reactStrictMode: false,
}

reactStrictModeはReact アプリケーションのパフォーマンスやセキュリティの問題を検出するための機能なので、長期的にfalseにするのはオススメされない

このライブラリを使うならこのISSUEが解決されるのを待たなければならないが、このライブラリを使うのをやめて

@googlemaps/react-wrapper@types/google.mapsを使う方法もあるみたい

ちょっと様子をみる

【SEO】FAQのリッチリザルト

FAQのリッチリザルトというのを知ったので調査した

developers.google.com

リッチリザルトとはGoogleの検索結果を、通常とは違うインタラクティブな状態で表示させること

例えば、よくある質問の質問と回答を以下のようなアコーディオンに表示させることをさす

構造化データというのを用意すると上図のようなユーザーにリーチしやすい状態にしてくれる

構造化データは以下のようなscriptタグで、これをサイトのhead内に配置するだけでリッチリザルトになる

<script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "FAQPage",
      "mainEntity": [{
        "@type": "Question",
        "name": "質問1",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "回答1"
        }
      }, {
        "@type": "Question",
        "name": "質問2",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "回答2"
        }
      }
    </script>

ちなみにtextには以下のhtmlタグが利用できる

<h1> から <h6>、<br>、<ol>、<ul>、<li>、<a>、<p>、<div>、<b>、<strong>、<i>、<em

また、構造化データは以下のようにクライアントサイドのレンダリング時にfetchしたデータを使って作ることもできる

fetch('https://api.example.com/recipes/123')
.then(response => response.text())
.then(structuredDataText => {
  const script = document.createElement('script');
  script.setAttribute('type', 'application/ld+json');
  script.textContent = structuredDataText;
  document.head.appendChild(script);
});

Generate Structured Data with JavaScript | Google Search Central  |  Documentation  |  Google Developers

リッチリザルトのタイプは「よくある質問」以外にもあるので、適したものがあれば試してみたい
Structured Data Markup that Google Search Supports | Google Search Central  |  Documentation  |  Google Developers

テストは以下のサイトでできる
Rich Results Test - Google Search Console

【Nuxt】Nuxt3の安定版がリリースされた

今日Nuxt3が安定版になったのを知った

nuxt.com

以前から使われていて評判は聞いていたが、安定版ではないということで調べていなかった

関わっているある案件ではvue2を使っていて、バージョンアップの機会をうかがっているのでNuxt3がどのようなものかざっくり調べてみる

Nuxtとは

Vue.js を使用したウェブアプリケーションを構築するためのJavaScriptフレームワーク

以下の特徴を持つ

  • 高パフォーマンス
  • 設定なしのTypeScriptサポート
  • SSRとSPAハイブリットサポート
  • 自動インポート
  • ファイル システム ルーティング

など

これらを実現するために使用しているアーキテクチャ

  • h3 HTTPフレームワークとNitro サーバーエンジンを採用
  • トランスパイラとしてのesbuildとバンドラーとしてWebpack5またはViteを採用
  • ルーティング ライブラリにvue-routerを採用
  • nuxi CLIツール

など

気になったライブラリをみてみた

esbuild

esbuildはGo言語で開発されたviteやwebpackに並ぶビルドツールの一種

esbuild.github.io

バンドルもできるが、Nuxtはesbuildのトランスパイル機能を使用している

H3とは

超軽量なHTTPフレームワーク

github.com

Nitroサーバーエンジン

nitro.unjs.io

  • 同じコードベースから、さまざまなホスティングプロバイダーに適した出力形式を生成
  • サーバーレス環境のサポート
  • APIルーティングサポート(h3の使用)
  • 自動的にコードスプリッティング
  • SSRとSPAのハイブリッドモードサポート
  • 開発用サーバーではホットリロード

などなど

自動インポートなど無駄なソースコード量を抑えられる機能が嬉しい反面、プロジェクト固有なちょっと変わった使い方をしたい時に困るかもと思った

ただ、全体的に開発体験的には他のフレームワークと遜色ない感じだし、vue使っているなら乗り換え先としてよさそう