ジャンプ率ジェネレーターの続きです。以前、React環境でいったん完成しましたが、この時実現できなかったページごとのOGP設定を実現すべく、前回作成したNextスターターキットで再度作り直しました。これによってReact環境とNext環境ではCSS in JS(Styled-components)の挙動に差異があることもわかりました。それではいきましょう!
【目次】
- 前回のおさらい
- 作ったもの
- 環境構築
- ファイル構成
- 共通テキスト設定(data.json)
- トップページ(index.tsx)
- Aboutページ(about.tsx)
- Innerコンポーネント(style属性で設定)
- 最後に
※参考:前回記事
【React】styled-componentsにフックの値を設定し、動的にスタイルを変更(ジャンプ率ジェネレーター完成!) - クモのようにコツコツと
※参考:ReactでWebアプリを作るシリーズまとめ
qiita.com
前回のおさらい
ReactのSPAのため、ページごとのOGP設定はうまくいかなかった。
※参考:前回記事
【React】styled-componentsにフックの値を設定し、動的にスタイルを変更(ジャンプ率ジェネレーター完成!) - クモのようにコツコツと
その後、Nextスターターキットを作成し、ページごとのOGP設定ができるようになった。
※参考:【React】ReactでWebアプリを作るシリーズまとめ(随時更新) - Qiita
ジャンプ率ジェネレーターもNext環境で作り直してOGPを設定したい。
作ったもの
文字ジャンプ率ジェネレーター(Next環境で作り直した)
ツマミを動かすと行長、行間、ジャンプ率の変更が下のサンプルに反映される
CSSの文字設定値も表示されるので適切な設定値を検討することができる。
プレビュー
jump-rate-generator-2.vercel.app
Aboutページ(こちらにも固有のOGPが表示される!)
jump-rate-generator-2.vercel.app
ソースコード
※参考:GitHub - ryo-i/jump-rate-generator-2
環境構築
React版のジャンプ率ジェネレータのときと同じ手順
- Nextスターターキットのリポジトリを
git clone
でクローン(アプリ名「jump-rate-generator-2」は最初から指定) cd
コマンドでフォルダに移動しnpm install
でパッケージをインストール- GitHubで新リポジトリ「jump-rate-generator-2」を作成
- 「.git」フォルダを削除して
git init
で再作成 git remote add origin
でリポジトリと紐づける
※参考:【React】文字ジャンプ率ジェネレーターを作るシリーズ始動!(環境構築編) - クモのようにコツコツと
ファイル構成
React版とNext版のファイル構成を比較
- React版は「/src」の中にコンポーネント、モジュール、スタイル、データ全てを入れ、静的なファイルは「/public」にある
- Next版ではコンポーネントからページ設定は「/pages」に分け、その他は「/components」、他のフォルダはルート直下に
ソースコード(React版)
※参考:GitHub - ryo-i/jump-rate-generator
ソースコード(Next版)
※参考:GitHub - ryo-i/jump-rate-generator-2
共通テキスト設定(data.json)
複数ページにわたるテキストを「/data/data.json」に設定
{ "head": { "url": "https://jump-rate-generator-2.vercel.app/" }, "header": { "title":"ジャンプ率ジェネレーター", "text": "文字ジャンプ率を動的に変えることができます" }, // 後略
トップページ(index.tsx)
トップページは「/pages/index.tsx」に設定
各種インポート
import Head from 'next/head'; import Header from '../components/Header'; import Inner from '../components/Inner'; import Footer from '../components/Footer'; import Data from '../data/data.json';
- Next.jsから
Head
をインポート Header
、Inner
、Footer
コンポーネントをインポート- data.jsonからテキストをインポート
Header
、Footer
コンポーネントはNextスターターキットと変更なし
※参考:【React】Nextスターターキットを作った-2. コンポーネント編(Next + TypeScript + CSS in JS) - クモのようにコツコツと
Inner
コンポーネントについては後述
テキスト設定
const headerTitle = Data.header.title; const headerText = Data.header.text; const pageTitle = 'ジャンプ率ジェネレーター'; const pageText = '行長、行間、ジャンプ率などを変えてみてください。';
headerTitle
とheaderText
はData
から取得pageTitle
とpageText
はベタガキ
Home
コンポーネント作成
function Home() { return ( <> <Head> <title>{ headerTitle }</title> <meta name="description" content={ headerText } /> <meta property="og:title" content={ headerTitle } /> <meta property="og:description" content={ headerText } /> </Head> <Header /> <main> <h1>{ pageTitle }</h1> <p dangerouslySetInnerHTML={{ __html: pageText }}></p> <Inner /> </main> <Footer /> </> ) }
React版はreact-routerとhelmetを使ってheadタグを設定したがSPAの動的な変更のためOGPに反映されなかった。
※参考:【React】OGPはつらいよ ーSPAでの動的OGP・失敗編ー(Reactアプリスターターキット) - クモのようにコツコツと
Next版ではindex.tsxに直接OGP設定を書くことで静的なheadタグが生成される!
※参考:【React】Nextスターターキットを作った-3. ページファイル編(Next + TypeScript + CSS in JS) - クモのようにコツコツと
最後にHome
コンポーネントをエクスポート
export default Home;
Dev-toolsの「Sources」を見ると静的なOGP設定になっていることがわかる!
※参考:ジャンプ率ジェネレーター
Aboutページ(about.tsx)
Aboutページは「/pages/about.tsx」にある
各種インポート
import Head from 'next/head'; import Header from '../components/Header'; import Profile from '../components/Profile'; import Footer from '../components/Footer'; import Data from '../data/data.json';
- Next.jsから
Head
をインポート Header
、Profile
、Footer
コンポーネントをインポート- data.jsonからテキストをインポート
Header
、Profile
、Footer
コンポーネントはNextスターターキットと変更なし
※参考:【React】Nextスターターキットを作った-2. コンポーネント編(Next + TypeScript + CSS in JS) - クモのようにコツコツと
テキスト設定
const headerTitle = Data.header.title; const pageTitle = 'このアプリについて'; const pageText = '文字の行長、行間、ジャンプ率を動的に変更した画面を確認することができます。'; const headTitle = pageTitle + ' | ' + headerTitle;
headerTitle
はData
から取得pageTitle
とpageText
はベタガキheaderText
はpageTitle
とheaderTitle
の組み合わせ
先ほどのトップページと同じ
About
コンポーネント設定
// Component function About() { return ( <> <Head> <title>{ headTitle }</title> <meta name="description" content={ pageText } /> <meta property="og:title" content={ headTitle } /> <meta property="og:description" content={ pageText } /> </Head> <Header /> <main> <h1>{ pageTitle }</h1> <p dangerouslySetInnerHTML={{ __html: pageText }}></p> <section> <h2>初期値</h2> <p>下記を推奨スタイルとして初期値にしています。</p> <ul> <li>行長:35文字( max-width: 35em; )</li> <li>行間:1.75倍( line-height: 1.75em; )</li> <li>ジャンプ率:200%( font-size: 2em; )</li> </ul> <p>※参考:<a href="https://www.i-ryo.com/entry/2019/02/19/230354">【行長・行間・ジャンプ率】タイポグラフィ事始め(適度な箱組みとは)</a></p> </section> <Profile /> </main> <Footer /> </> ); }
トップページと同じくOGP設定はabout.tsxに直に設定。また、sectionタグの部分は本ページ固有の内容のためベタガキ。
最後にAbout
コンポーネントをエクスポート
export default About;
Dev-toolsの「Sources」を見ると静的なOGP設定になっていることがわかる!
Innerコンポーネント(style属性で設定)
文字設定を変更するジェネレーター本体はInnerコンポーネントに書いている。
※参考:jump-rate-generator-2/Inner.tsx at main · ryo-i/jump-rate-generator-2 · GitHub
React版の時は関数コンポーネントの中でStyled-coponentsで設定していた
const P = styled.p` line-height: ${lineHeight}em; `; const Section = styled.section` max-width: ${lineLength}em; `; const H2 = styled.h2` && { font-size: ${jumpRate}em; } `;
上記のコンポーネントをJSXでレンダリングしていた
<Example> <Section> <H2>タイトルです、ああタイトルです、タイトルです</H2> <P>本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。</P> </Section> </Example>
※参考:【React】styled-componentsにフックの値を設定し、動的にスタイルを変更(ジャンプ率ジェネレーター完成!) - クモのようにコツコツと
しかし、上記のままだとNext版では変更が反映されなかった。
React版はSPAのためJSXのHTMLがリアルタイムにレンダリングされる。CSS設定が変更されるとStyled-componentsがタグに振っているclass名も動的に変更される。
しかしNext版の場合はStyled-componentsが振っているclass名が固定されたままなのでCSSの設定も変わらない。Next.jsのHTMLタグはSPAに比べて静的なHTMLということだ。
Next.jsでCSSを動的に変更する方法に調べ、いろいろ試してみたが自分の環境ではうまくいかなかった。。
※参考:Next.jsでstyled-componentsを使うときに最初に設定しておくこと
※参考:Advanced Features: カスタム `Document` | Next.js
※参考:Next.jsにstyled-componentsを取り込む方法【Babelの設定が必要】
※参考:GitHub - styled-components/babel-plugin-styled-components: Improve the debugging experience and add server-side rendering support to styled-components
※参考:styled-components: Advanced Usage
※参考:next.js/_document.js at master · vercel/next.js · GitHub
そもそも自分がやりたいことが違うのかもしれない。styled-componentsの動的変更について調べるとたいていはpropsと分岐条件で値を変更する内容。
styled-componentsのclass名がリアルタイムに都度代わる方法はNextとは相性が悪いように感じる。
Reactドキュメントにはインラインスタイル(style属性を直接変更)についてこうあった。
style 属性を要素のスタイリングの主要な手段として使うことは一般的に推奨されません。多くの場合、className を使って外部の CSS スタイルシートに定義された CSS クラスを参照するべきです。React アプリケーションの中では、style は動的に計算されたスタイルをレンダー中に追加するために最もよく使われます
※参考:DOM 要素 – React
「動的に計算されたスタイルをレンダー中に追加する」は今回の状況に合っているのではないか。それ以外の基本的なスタイル設定はstyle-componentsを使ってclassNameで設定できているわけで。
先ほどstyled-componentsで設定していた部分をただの連想配列にする
const pStyle = { lineHeight: lineHeight + 'em' }; const sectionStyle = { maxWidth: lineLength + 'em' }; const h2Style = { fontSize: jumpRate + 'em' };
キー名はハイフン(line-height
など)ではなくキャメルケース(lineHeight
など)
※参考:DOM 要素 – React
section、h2、pはただのタグに戻して、style属性で先ほどの設定を読み込む。
<Example> <section style={sectionStyle}> <h2 style={h2Style}>タイトルです、ああタイトルです、タイトルです</h2> <p style={pStyle}>本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。本文です。本文です。本文ですったら、本文です。</p> </section> </Example>
- sectionタグの
style
属性にsectionStyle
を設定 - h2タグの
style
属性にh2Style
を設定 - pタグの
style
属性にpStyle
を設定
※参考:jump-rate-generator-2/Inner.tsx at main · ryo-i/jump-rate-generator-2 · GitHub
これでツマミをいじるとCSSが動的に変更されるようになった!
Dev-toolsの「Elements」を見るとタグにstyle属性が追加されているのがわかる。
styles-componentsのclass名は変更がないまま。
※参考:ジャンプ率ジェネレーター
最後に
ということでジャンプ率ジェネレータをNext版に作り直しました。
ReactのSPAとNext.jsの静的HTMLによってCSS in JSの挙動に違いがあるのがちょっと戸惑いましたが、全体的にはOGPやルーティング以外のコアな部分のコンポーネントはほとんど変更がないままスムーズに作り直すことができました。ページごとのOGPがちゃんと表示さっるのも嬉しいです♪
こんな感じで今後もしばらくはNext環境でWebアプリを作っていきたく思います。それではまた!
※参考:ReactでWebアプリを作るシリーズまとめ
qiita.com