開発者ドキュメント

ReactアプリケーションサーバーでCSSをレンダリングする方法

序章

Next.js (React)および Nuxt.js (Vue)は、アプリビューをサーバーにレンダリングするプロセスを合理化するのに役立ちます。

開発に対応する方法でReactコンポーネントにCSSをレンダリングするためのソリューションが引き続き必要です。 また、スタイルを使用できるように、サーバーでCSSをレンダリングするためのソリューションも必要になります。

この記事では、CSSのレンダリングの課題を確認してから、 styled-componentsstyled-jsx Next.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-プロジェクトの設定

開始するには、ターミナルを開き、プロジェクト用の新しいフォルダを作成します。

  1. mkdir css-ssr-next-example

次に、新しいプロジェクトディレクトリに移動します。

  1. cd css-ssr-next-example

次に、次のコマンドを実行して初期化します。

  1. npm init -y

これにより、 package.json 依存関係を追跡するために使用するファイル。

次に、Next.js、React、およびReactDOMをインストールします。

  1. 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 脚本:

package.json
{
  "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 ディレクトリ:

  1. mkdir pages

このディレクトリに、 index.js 次の内容のファイル:

pages / index.js
import React from 'react';

const Index = () => <h1>Hi, new Next.js project</h1>;

export default Index;

今実行します dev サーバーを起動するスクリプト:

  1. npm run dev

開いたら localhost:3000 Webブラウザーでは、次のことがわかります。

Output
Hi, new Next.js project

まず、 Head Nextのコンポーネントを使用してスタイルを正規化します normalize.css:

pages / index.js
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プロジェクトのルートにあるフォルダー:

  1. mkdir static

このディレクトリに、 base.css 次のCSSコンテンツを含むファイル:

static / base.css
body {
  font-family: 'Raleway', sans-serif;
  color: #222;
}

をインポートします base.css インデックスページのファイル:

pages / index.js
// ...

    <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:

  1. npm install styled-components@5.3.0

次に、 components ディレクトリ:

mkdir components

このディレクトリに、 Button.js ファイルを作成し、次のようにファイルを更新します。

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 インデックスページのコンポーネント:

index.js
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開発ツールを使用して、ページソースを検査します。

コンテンツはサーバーにレンダリングされますが、ボタンに関連するページのどこにもスタイルは表示されません。 一方、適用されたフォントスタイルからわかるように、外部ファイルがサーバーに正常にレンダリングされたことがわかります。

では、コンポーネントスタイルの何が問題になっているのでしょうか。 コンソールを見てください:

Output
Warning: 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:

components / Button.js
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つの要素のみで構成されていない場合:

components / TitleAndButton.js
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-componentsstyled-jsx Next.jsプロジェクトのサーバー上。

Next.jsについて詳しく知りたい場合は、 Next.js入門テクニカルトークを試すか、Next.jsトピックページで演習とプログラミングプロジェクトを確認してください。 。

モバイルバージョンを終了