とーますメモ

Ruby on Rails / Goなどの学習メモ

【Next.js】Material UIをSSRで使う方法

何も考えずにNext.jsでMaterial UIを使おうとすると以下のエラーが出ます。

Warning: Prop 'className' did not match. Server ...

Material UIではSSRへの対応方法が準備されており、以下がそのサンプルです。
material-ui/examples/ssr at master · mui-org/material-ui · GitHub

上記のサンプルコードを初見で見て思ったのが、どこがポイントなのよ〜ってこと。
余計なコードがいろいろはいってて、どこがポイントなのか初心者にはわかりにくいです。

色々検証してわかったのは、以下のコードを追加すれば直るってこと。

_app.tsx: useEffectのところのみ必要。

import React from 'react';

export default function MyApp({ Component, pageProps }: AppProps) {
  React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles) {
      jssStyles.parentElement!.removeChild(jssStyles);
    }
  }, []);
  ....
  return <Component {...pageProps} />;
}

_document.tsx
ServerStyleSheetsをインポートする箇所と、
MyDocument.getInitialPropsを入れればOK

import { ServerStyleSheets } from '@material-ui/core/styles';
...
...
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
  // Resolution order
  //
  // On the server:
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. document.getInitialProps
  // 4. app.render
  // 5. page.render
  // 6. document.render
  //
  // On the server with error:
  // 1. document.getInitialProps
  // 2. app.render
  // 3. page.render
  // 4. document.render
  //
  // On the client
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. app.render
  // 4. page.render

  // Render app and page and get the context of the page with collected side effects.
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
    });

  const initialProps = await Document.getInitialProps(ctx);

  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
  };
};

ただ自分の場合、next.config.jsでreactStrictMode: trueをしてたためエラーがで出続けていました。これがわかるまでに結構大変でした。
潜在的な問題点を洗い出すためにtureにしたほうが良いようなのですが
Material UIと一緒に使う場合は、無効にしたほうが良さそう。
Next.js 4年目の知見:SSRはもう古い、VercelにAPIサーバを置くな - Qiita

Material UI v5では直ってるっぽいので、もうちょっとreactStricModeを使うのは待つほうが良いかも...
[styles] Strict Mode support · Issue #18018 · mui-org/material-ui · GitHub

[参考]
Material-UIでNext.jsのポイントを紹介する|fumi|note
フロントエンド初学者がNext.js + Typescript + FireStore + Material-UI + SSGでサイト作るまでのメモ
【Next.js】Material-UI導入時に[Warning: Prop `className` did not match. ]が発生した場合の対処法 - Qiita
Server Rendering - Material-UI

【GraphQL】GraphQL Code Generatorについてのメモ

GraphQL Code Generatorとは、GraphQLのスキーマからTypeScriptの型定義ファイルを作成することができるツール。

テスト環境はNext.js + TypeScript + Apollo + GraphQL Code Generator + Hasuraの構成する。CSRでGraphQLリクエストはせず、SSRとSSG内でのみGraphQLリクエストを行う前提。

余計なプラグインは入れずに、最低限の設定でGraphQLへqueryとmutationを使用できる設定にする。

インストール

$ npm i -D graphql @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-document-nodes

参考: https://www.graphql-code-generator.com/docs/plugins/index

@graphql

=> (必須) GraphQLパッケージ(そもそもこれがないと動かない)

@graphql-codegen/cli

=> (必須) 本体 (型定義ファイルジェネレーター本体)

@graphql-codegen/typescript

=> (必須) TypeScriptの型定義ファイルを生成するのに必要

@graphql-codegen/typescript-operations

=> (必須) ユーザ定義したquery, mutation, subscription, fragmentの型定義ファイル生成

@graphql-codegen/typescript-document-nodes

=> (.graphql)ファイルから(.ts)ファイルを生成し、型定義ファイルに追加してくれる。
導入することで、以下のメリットがある
1) ApolloClientので呼び出すときに、逐一「gql'...'」をつけなくて良い。
2) 型定義ファイルにquery, mutation, subscription, fragmentが追加されるので、importが減りわかりやすい。

@graphql-codegen/fragment-matcher

=> GraphQLのinterfaceやunion(TypeScriptのinterfaceのことではない)を使用している場合に必要。使用する場合InMemoryCacheの引数を設定する必要あり?
@see: https://qiita.com/daiki7nohe/items/8a3d79d0bebf2166f32d

@graphql-codegen/typescript-graphql-files-modules

d.tsファイルを生成してくれる。パッケージ作成時に必要らしいが、パッケージを作成しないなら不要という認識

@graphql-codegen/typescript-react-apollo

=> useQueryのように使える独自ReactHooksを生成!内部でuseQueryやuseMutationを使用している。
@see: https://qiita.com/pure-adachi/items/f1e03941e8c0ac47c7ee
@see: https://developer.medley.jp/entry/2020/11/06/180208

@graphql-codegen/typescript-graphql-request

=> Apollo使わないでGraphQLリクエストするときは導入を考える。

備考: graphqlと@graphql-codegen/cliは、グローバルにインストールすることは非推奨にされている。
Installation

設定

codegen.yml内で環境変数を読み込む方法

Hasuraのエンドポイントとか、HASURA_GRAPHQL_ADMIN_SECRETなんかは、環境変数から読み込ませたい。そんなときは"-r dotenv/config"のオプションをつけて生成すればOK.

"scripts": {
  ...
  "codegen": "graphql-codegen -r dotenv/config"
  ...
}

ただしデフォルトだと.envからしか読み込まないので、.env.localなど他の環境変数ファイルから読み込ませたいときは以下のようにする。

"scripts": {
  ...
  "codegen": "DOTENV_CONFIG_PATH=./.env.local graphql-codegen -r dotenv/config"
  ...
}

[参考]
codegen.yml
Support multiple .env files. · Issue #4635 · dotansimha/graphql-code-generator · GitHub

=====================================

【VSCode】Apollo GraphQLをHasuraと組み合わせて使う方法

下記のページを参考に設定
Guides: Visual Studio Code Setup | Hasura GraphQL Docs

インストール

まずはVSCodeにプラグインのインストール
Apollo GraphQL - Visual Studio Marketplace

このプラグインを入れるとGraphQLにシンタックスハイライトがつき、GraphQL入力時に、補完が使えるようなるのでApollo + GraphQLを使うなら必須。

インストール後、apollo.config.jsをルートディレクトリに作成し、
自分の場合はHeroku上のHasuraのサーバを置いているので、以下のように設定する。

name: 任意の名前
url: HasuraのエンドポイントURL
x-hasura-admin-secret:
=> Heroku上のHasuraのアプリを選択 => Settings => Config Varsに
HASURA_GRAPHQL_ADMIN_SECRET: SECRET_KEY
と同じSECRET_KEYを入れる

(補足) HASURA_GRAPHQL_ADMIN_SECRETの設定の仕方
Run Hasura GraphQL engine on Heroku | Hasura GraphQL Docs

module.exports = {
  client: {
    service: {
      name: "<任意の名前>",
      url: "<HasuraのエンドポイントURL>",
      headers: {
        "x-hasura-admin-secret": "<SECRET_KEY>"
      }
    }
  }
};

VSCode上で、⌘ + Shift + Pで"Apollo: Reload Schema"を選択すれば設定が読み込まれるので、これでエラーが出なければ補完が効くようになる。

[参考]
Hasura Authentication Explained

【VSCode】Next.jsのコードをデバックする方法

Tl;dr

ルートディレクトリに.vscodeフォルダを作り、launch.jsonを以下の内容で作成する。

$ mkdir .vscode && cd .vscode
$ touch launch.json

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next: Node",
      "type": "node",
      "request": "attach",
      "skipFiles": ["<node_internals>/**"],
      "port": 9229
    },
    {
      "name": "Next: Chrome",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3001",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "webpack://_N_E/*": "${webRoot}/*"
      },
      "port": 9222
    }
  ]
}

バックエンド用

SSRやSSGの関数内で使用するため。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next: Node",
      "type": "node",
      "request": "attach",
      "skipFiles": ["<node_internals>/**"],
      "port": 9229
    }
  ]
}

request: "launch"を設定している人も多いが、自分は既に起動しているプロセス上でデバックしたかったので、attachを選択。

クライアント用

まずはChrome用の拡張である「Debugger for Chrome」をインストール。
Debugger for Chrome - Visual Studio Marketplace

これをインストールすると、type: "chrome"でエラーが出なくなる。
またクライアント用でもrequest: "attach"ができるみたいだけど、よくうまく動作しなかったので、こちらはlaunchで設定。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next: Chrome",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3001",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "webpack://_N_E/*": "${webRoot}/*"
      },
      "port": 9222
    }
  ]
}

[参考]
VSCodeで便利にdebugする方法 | CYOKODOG

Instagramでフォロワーをうまく集める方法についてのメモ

基本ルール

自己満足を排除し、読者に支持されるものを提供する

プロフィール欄をきれいに簡潔に書くこと

興味を持てくれた人は、プロフィールを見てフォローするかを決めるので、
しっかり書いていく。

写真をまずは6〜7枚投稿してから、他のユーザにアプローチしていく。

自分に投稿もないのにフォロワーは増えない。自分の投稿に関連性がありそうなユーザの投稿を地道にLikeしていく。フォローする必要はない。
フォロワーではないユーザの写真にいいねをするだけ。

投稿の頻度をキープすること。

理想は2~3日に1回

ハッシュタグを上手に使う

1つの投稿につき、30個までつけれる。おすすめはハッシュタグを10個以上つけること。
写真に適切なハッシュタグを見つけることが大事。

流行りのタグや、ファンが多いタグがどれかは日々変化していくため
どのハッシュタグが人気かを把握するのが大事。
ライバルの写真にどのようなハッシュタグをつけているのかを見てリストを作るのが一番効率的。

そして、例えば25個のハッシュタグをすべての投稿で共通のものをコピペして使い、残りを投稿に合わせてカスタマイズするのも良いでしょう。そうすることによってハッシュタグをつける時間の節約になります。

競合率が高いはビックワードではなく、スモールワードやミドルワードを狙う。

ビッグワード
投稿数・検索する人が多いハッシュタグ(投稿10万件以上)
ミドルワード
投稿数・検索する人がそこそこいるハッシュタグ(投稿1~10万件)
スモールワード
投稿数・検索する人が少ないハッシュタグ(投稿1万件以下)

ハッシュタグは以下のサイトで検索
Instagramハッシュタグ検索
Instagram(インスタグラム)ハッシュタグ検索ツール | ハシュレコ
おすすめハッシュタグ発見ツール|インスタグラム(instagram)のフォロワー増加のコツとツール方法。タグ映えで集客収益化狙うなら無料のマーケティングツールならインスタツール

ハッシュタグの一括投稿件数検索
ハッシュタグ人気度調査|インスタグラム(instagram)のフォロワー増加のコツとツール方法。タグ映えで集客収益化狙うなら無料のマーケティングツールならインスタツール

フィルターを活用する。

使用したフィルターのハッシュタグをつけることで、そのセグメントの人達を集めることができる。例: #nofilter
また投稿する全ての写真に同じフィルターを使い一貫性を持たせることでファンを獲得する。

投稿を行う時間帯(タイミング)に注意する。

より多くの人に見てもらう必要があるので、平日の通勤時間や、お昼休憩の時間、夜、もしくは休日の夜に投稿するのをおすすめします。

予約投稿を使用し、とりあえずは朝の6~7時ごろに投稿してみる。

ライバルのフォロワーにリーチする。

フォロワーにエンゲージする方法は以下の3つ。
・ユーザーをフォローする。
・写真に「いいね!」する
・写真にコメントする。

彼はライバルのフォロワーの100人をフォローし、その後、別の100人にフォロー&「いいね!」をし、また別の100人に対してフォロー&「いいね!」&コメントをしました。以下がテストの結果です。

フォローのみ: 14%のフォローバック
フォロー&「いいね!」: 22%のフォローバック
フォロー&「いいね!」&コメント: 34%のフォローバック
結果はとても明快です。深くリーチすればするほど、フォローバックしてくれる確率は上がります。

キャプションを充実させる

写真をトリガーにしてしっかり文章を読んでもらい興味を持ってもらう。

今のトレンドや季節のイベントに便乗した投稿を行う。

トピックやイベントに関する投稿をしたり、特定の記念日のハッシュタグを使うのはいい方法。

[参考]
2021年にインスタグラムでフォロワーをもっと増やす! 12の方法をご紹介
ガツンとフォロワーを増やす!Instagramで超大事な5つのポイント
インスタグラムのフォロワーを増やす37の方法とは?【1年で30万フォロワー】│OTONARIメディア

【Next.js】Netlifyの設定についてのメモ

目標1: Next.jsプロジェクト(プレレンダリング + SSG)をNetlifyで公開したい
目標2: Next.jsプロジェクト(SSR + SSG)をNetlifyで公開したい

Netlifyアカウント作成

基本的には以下のサイトさんをみて設定
【5分で公開・簡単】Netlifyの使い方を解説する - GOOTA TECH

  1. GithubアカウントでSign up
  2. プロジェクトの作成
  3. Git ProviderにGithubを選択
  4. Netlifyに紐付けるリポジトリの設定

目標1: Next.jsプロジェクト(プレレンダリング + SSG)をNetlifyで公開したい

デプロイ設定

netlify.tomlで設定する。このファイルが存在している場合、NetlifyのBuild settingにある設定は無視される。

[build]
  command = "npm run build && npm run export"
  publish = "out"

[[plugins]]
  package = "@netlify/plugin-nextjs"
[[plugins]]
  package = "netlify-plugin-cache-nextjs"

これでプレレンダリングとSSGのみで構成されているNext.jsプロジェクトのデプロイ設定ができる。npm run exportの設定は、予めpackage.jsonに記述されている必要がある。
ない場合「Deploy directory 'out' does not exist 」というエラーが出る。
deployment - Deploy did not succeed: Deploy directory 'out' does not exist - Stack Overflow

デプロイは「Deploy site」のボタンをクリックすることで、ビルドされそのファイルがoutディレクトリに配置される。

目標2: Next.jsプロジェクト(SSR + SSG)をNetlifyで公開したい

デプロイ設定

同じくnetlify.tomlで設定する。静的サイトではなくSSRが入ることで動的リクエストになるため、exportとpublishの設定を除外し、next.config.jsのtargetに"serverless"を設定する。

netlify.toml

[build]
  command = "npm run build"

[[plugins]]
  package = "@netlify/plugin-nextjs"
[[plugins]]
  package = "netlify-plugin-cache-nextjs"

next.config.js

module.exports = {
  ...
  target: 'serverless',
  ...
};

これで「Deploy site」のボタンを押すか、mainブランチにpushすると自動的にビルドが走り、SSRプロジェクトがデプロイされる。

補足

昔は、SSRをNetlify上で使用するには、Next on Netlifyプラグインをインストールする必要があったらしいが、今はこのプラグインは廃止され、標準パッケージであるnext.js build pluginが代わりに使用される。tomlファイルを使用しない場合は、標準で入っているので何もしないで良いが、

As of v3.0.0, all new sites deployed to Netlify with Next.js will automatically install this plugin for a seamless experience deploying Next.js on Netlify!

This means that you don't have to do anything — just build and deploy your site to Netlify as usual and we'll handle the rest.

GitHub - netlify/netlify-plugin-nextjs: A build plugin to integrate Next.js seamlessly with Netlify

使用する場合は以下のようにプラグインとして指定する必要がある。

package = "@netlify/plugin-nextjs"

[参考]
https://wp-kyoto.net/netlifynext-jsssrserverless-mode/
next.config.js: 构建目标 | Next.js

【React】実装方針メモ

・コンポーネントはクラスコンポーネントではなく、関数コンポーネントを使用する。
・Atomic Designをベースにコンポーネントを管理する
自分はとりあえずこの構成でやる。

- src
  - pages (only container: データ取得、APIアクセス、ロジック)
  - components
    - templates (only presentational)
    - organisms (container or presentational)
      - list
        - container.tsx (ロジックのみ。データ取得やAPIアクセスはここではしない)
        - presentational.tsx
    - molecules (only presentational)
      - item.tsx
    - atoms (only presentational) または material-uiなどのUIツール
      - button.tsx
      - input.tsx

・Pages ComponentからしかAPIを叩かない。
・Container ComponentとPresentational Componentに分けて実装する
・スタイル管理はstyled-componentsを使用する。
・HTTPクライアント(Ajax対応)はIE11対応を考えてaxiosを使用する。
axiosとfetchの違いはこのサイトさんの説明が良かった。
【JavaScript】FetchAPIとaxiosの違いって?機能やメリットを比較
・Ajaxのキャッシュ、リトライ、ポーリングといった機能を実装するには
React Queryを使用する。SWRもあるが、React Queryのほうが良さげか?
データ取得ライブラリ「React Query」のススメ│uniface.hub
REST API なら React Query がファーストチョイス

[参考]
React Componentの実装ルールを決めてみた | Money Forward Engineers' Blog
ぼくがかんがえたさいきょうのAtomic Design - Qiita
React Hooks ✕ AtomicDesignで画像投稿webアプリのフロントエンドを実装する - Qiita

私のReactのコンポーネント実装アンチパターン - Qiita
Reactで読みやすいコードを書くための心得 - ログミーTech
コンポーネントを実装するときに意識すること - bagelee(ベーグリー)
Reactを使ったフロントエンドのアーキテクチャ事例 | Fintan
デザイナーがデザインツールを使わずに、Reactを使ってデザインした話 - Medley Developer Blog
No more ガタンッ――React/Redux、Atomic Design、CSS Modulesを取り入れたアメブロのフロントエンド開発の裏側:大規模ブログサイト表示速度改善 大解剖(2)(2/2 ページ) - @IT