ReactアプリケーションサーバーでCSSをレンダリングする方法
序章
Next.js (React)および Nuxt.js (Vue)は、アプリビューをサーバーにレンダリングするプロセスを合理化するのに役立ちます。
開発に対応する方法でReactコンポーネントにCSSをレンダリングするためのソリューションが引き続き必要です。 また、スタイルを使用できるように、サーバーでCSSをレンダリングするためのソリューションも必要になります。
この記事では、CSSのレンダリングの課題を確認してから、 styled-components
と styled-jsx
Next.jsプロジェクトのサーバー上。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- Node.jsのローカル開発環境。 Node.jsをインストールしてローカル開発環境を作成する方法に従ってください。
このチュートリアルは、Nodev16.2.0で検証されました。 npm
v7.14.0、 react
v17.0.2、 react-dom
v17.0.2、 next
v10.2.3、および styled-compnents
v5.3.0。
Reactのスタイルパターンを理解する
ReactでCSSを作成する一般的な方法はいくつかありますが、すべて機能します。 状況に応じて、次のいずれかの方法でReactアプリにスタイルを適用します。
グローバルスタイル
グローバルスタイルは、ローカルまたはコンテンツ配信ネットワーク(CDN)でホストされるスタイルシートを含めるパターンです。
次に例を示します。
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.css" />
これは、コンポーネントの再利用を促進しないため、あまり好ましくないスタイリングパターンです。 また、スタイルの構成を奨励しません。
これらのCSSルールは、特定の要素またはコンポーネントに直接スコープされていません。 コンポーネントがインポート、ネスト、または拡張によって予期されていなかった方法で相互作用する場合、競合が発生する可能性が高くなります。
ただし、フォントの組み込みやCSSのリセットやデフォルトなど、スタイルをグローバルに含めることができる場合があります。
インラインスタイル
インラインスタイルは、Reactを使用してDOM要素またはReactコンポーネントに直接適用されます style
財産。 HTMLインラインによく似た実装 style
属性ですが、JavaScriptを使用します element.style
API。
次に例を示します。
const titleStyle = {
fontSize: '4rem';
lineHeight: '1.6';
color: '#222';
}
<h1 style={titleStyle} {...props}>{props.children}<h1>
このパターンは、スタイルとコンポーネントの構成、および再利用を促進します。
ただし、インラインスタイルでは、疑似クラスとターゲット疑似要素を使用してフォーカス状態のホバーを処理する方法は提供されません。 大規模で複雑なプロジェクトの場合、より堅牢なソリューションが必要になる場合があります。
コンポーネントスタイル
コンポーネントスタイルは、再利用を促進し、スタイルとコンポーネントをより適切に構成するのに役立ちます。 これを実現するには、ユーティリティまたはライブラリが必要です。 スタイルローダー、スタイルコンポーネント、グラマーなど。 コンポーネントスタイルをサポートするためのツールの例です。
styled-components
CSS-in-JSを実装するための一般的なソリューションです。 これらはインラインコンポーネントスタイルですが、複雑な(疑似)選択、ネストなどを実行するためのより強力な機能を備えています。
ステップ1-プロジェクトの設定
開始するには、ターミナルを開き、プロジェクト用の新しいフォルダを作成します。
- mkdir css-ssr-next-example
次に、新しいプロジェクトディレクトリに移動します。
- cd css-ssr-next-example
次に、次のコマンドを実行して初期化します。
- npm init -y
これにより、 package.json
依存関係を追跡するために使用するファイル。
次に、Next.js、React、およびReactDOMをインストールします。
- npm install next@10.2.3 react@17.0.2 react-dom17.0.2
この時点で、Next.js、React、およびReactDOMを使用した新しいプロジェクトが作成されます。
注:公開以来、Next.jsプロジェクトを作成するためのより最新のアプローチでは、create-next-appを利用できます。
今、更新します package.json
Next.jsアプリを起動するには dev
脚本:
{
"name": "css-ssr-next-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "next"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"next": "^10.2.3",
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
次に、を作成します pages
ディレクトリ:
- mkdir pages
このディレクトリに、 index.js
次の内容のファイル:
import React from 'react';
const Index = () => <h1>Hi, new Next.js project</h1>;
export default Index;
今実行します dev
サーバーを起動するスクリプト:
- npm run dev
開いたら localhost:3000
Webブラウザーでは、次のことがわかります。
OutputHi, new Next.js project
まず、 Head
Nextのコンポーネントを使用してスタイルを正規化します normalize.css
:
import React from 'react';
import Head from 'next/head';
const Index = () =>
<div>
<Head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" />
</Head>
<h1>Hi, new Next.js project</h1>
</div>;
export default Index;
次に、 static
Next.jsプロジェクトのルートにあるフォルダー:
- mkdir static
このディレクトリに、 base.css
次のCSSコンテンツを含むファイル:
body {
font-family: 'Raleway', sans-serif;
color: #222;
}
をインポートします base.css
インデックスページのファイル:
// ...
<Head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" />
<link rel="stylesheet" href="/static/base.css" />
</Head>
// ...
ブラウザでは、フォントがデフォルトのフォントからRalewayに表示されます。
この時点で、グローバルスタイルのNext.jsプロジェクトができました。
ステップ2–スタイル付きコンポーネントの使用
を使ってみましょう styled-components
コンポーネントをスタイルするためのライブラリ。
まず、インストールします styled-components
:
- npm install styled-components@5.3.0
次に、 components
ディレクトリ:
mkdir components
このディレクトリに、 Button.js
ファイルを作成し、次のようにファイルを更新します。
import React from 'react';
import styled from 'styled-components';
const ButtonBase = (props) => <button {...props}>{props.children}</button>
const Button = styled(ButtonBase)`
/* Rectangle 2: */
background: #0077E2;
box-shadow: 0 2px 7px 0 rgba(120,137,149,0.25);
border-radius: 3px;
text-transform: uppercase;
padding: 10px;
color: #fff;
border: #0077E2;
`
export default Button;
使用しています styled-components
としてインポート styled
スタイリングするには Button
. ButtonBase
ボタンのスケルトンを返します Button
スタイル付きのコンポーネントを返します ButtonBase
.
インポートして使用する Button
インデックスページのコンポーネント:
import React from 'react';
import Head from 'next/head';
import Button from '../components/Button'
const Index = () => <div>
<Head>
....
</Head>
<h1>Hi, new Next.js project</h1>
<Button>Clicker</Button>
</div>;
export default Index;
変更を保存し、ブラウザでアプリケーションを観察します。 テキストの下には、新しいスタイルのボタンがあります。
ただし、ハードリフレッシュ後、ボタンのスタイルは期待どおりになりません。
ボタンのスタイルが欠落しているように見えますが、どういうわけか、基本のスタイルはそのままです。 Web開発ツールを使用して、ページソースを検査します。
コンテンツはサーバーにレンダリングされますが、ボタンに関連するページのどこにもスタイルは表示されません。 一方、適用されたフォントスタイルからわかるように、外部ファイルがサーバーに正常にレンダリングされたことがわかります。
では、コンポーネントスタイルの何が問題になっているのでしょうか。 コンソールを見てください:
OutputWarning: Prop `className` did not match. Server: "sc-gtsrHT kbmjhF" Client: "sc-bdnxRM kbyRfM"
クラス名の不一致を示すエラーが表示される場合があります。 これは、リロードすると、コンテンツが最初にサーバーからフェッチされるためです。
不運にも、 styled-components
サーバーにレンダリングされないため、その時点では使用できません。
注:発行以来、 styled-components
サーバー側レンダリングをサポートします。
Next.jsのwith-styled-componentsの例も参照できます。
解決策を見てみましょう。
ステップ3–スタイル付きJSXの使用
Next.jsに取り組んでいるチームは、この問題を軽減するために、styled-jsxというライブラリを導入しました。 ライブラリは、作成したスタイルが、ブラウザだけでなく、サーバーとブラウザでレンダリングされることを保証します。
すでにNext.jsにバンドルされているので、何もインストールする必要はありません。
再訪 Button
コンポーネントを使用するように変更します styled-jsx
:
import React from 'react';
const Button = props => (
<button {...props}>
{props.children}
<style jsx>{`
background: #0077e2;
box-shadow: 0 2px 7px 0 rgba(120, 137, 149, 0.25);
border-radius: 3px;
text-transform: uppercase;
padding: 10px;
color: #fff;
border: #0077e2;
`}</style>
</button>
);
export default Button;
スタイリングするコンポーネントのルート要素の終了タグの前に、 style
要素と jsx
属性。 の中に style
要素、テンプレート文字列を含む中括弧を開きます。 文字列は有効なCSSスタイルであり、コンポーネントスタイルとしてサーバーである必要があります。
でセレクターを使用することもできます styled-jsx
コンポーネントが1つの要素のみで構成されていない場合:
import React from 'react';
const TitleAndButton = props => (<div {...props}>
<h1 className="title">Hi Title</h1>
<button>Clicker</button>
<style jsx>{`
h1.title {
color: #222
}
button {
background: #0077e2;
box-shadow: 0 2px 7px 0 rgba(120, 137, 149, 0.25);
border-radius: 3px;
text-transform: uppercase;
padding: 10px;
color: #fff;
border: #0077e2;
}
`}</style>
</div>);
export default TitleAndButton;
これで、インポートして使用できます TitleAndButton
インデックスページのコンポーネント。 両方の要素が期待どおりにスタイル設定されます。
注:Next.jsのwith-styled-jsxの例も参照できます。
styled-jsx
Next.jsプロジェクトでサーバーにスタイルをレンダリングするための1つのアプローチです。
結論
この記事では、CSSのレンダリングの課題について学び、次に使用しました styled-components
と styled-jsx
Next.jsプロジェクトのサーバー上。
Next.jsについて詳しく知りたい場合は、 Next.js入門テクニカルトークを試すか、Next.jsトピックページで演習とプログラミングプロジェクトを確認してください。 。