最新JavaScriptフレームワークを駆使!React、TypeScript、WebpackでスマートなCSSモジュール開発

2024-06-17

React、TypeScript、Webpack で CSS モジュールをインポートする方法

Webpack 設定ファイル (webpack.config.js) で、CSS モジュールを処理するためのローダーを構成する必要があります。

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader', options: { modules: true } },
        ],
      },
    ],
  },
};

上記の例では、style-loadercss-loader の 2 つのローダーを使用しています。

  • style-loader: 抽出された CSS を <style> タグに変換し、HTML の <head> タグに挿入します。
  • css-loader: CSS ファイルを JavaScript モジュールに変換し、Webpack のバンドルに含めます。 modules: true オプションは、CSS モジュールを有効にします。

CSS モジュールのインポート

React コンポーネントで CSS モジュールをインポートするには、import ステートメントを使用します。

import styles from './styles.module.css';

上記の例では、styles.module.css ファイルから CSS モジュールをインポートしています。Webpack はこのファイルを処理し、CSS クラス名をスコープ化された一意の名前に変換します。

CSS クラス名の使用

コンポーネントの JSX コードで、インポートされた CSS クラス名を使用できます。

<div className={styles.button}>ボタン</div>

上記の例では、styles.button クラスを使用して、ボタンのスタイルを設定しています。Webpack はこのクラス名をスコープ化された一意な名前に変換するため、スタイルが他のコンポーネントのスタイルと干渉することはありません。

補足

  • CSS モジュールを使用すると、コンポーネントの CSS スタイルをカプセル化し、グローバルな名前空間汚染を防ぐことができます。
  • TypeScript を使用すると、CSS モジュールの型を定義できます。これにより、コンポーネントで誤ったクラス名を使用するのを防ぐことができます。
  • Webpack は、CSS モジュールをバンドルし、本番環境用に最適化します。



    ファイル構成

    src
    ├── App.tsx
    ├── styles
    │   └── App.module.css
    └── index.html
    

    App.tsx

    import React from 'react';
    import styles from './styles/App.module.css';
    
    const App: React.FC = () => {
      return (
        <div className={styles.container}>
          <h1>CSS モジュール</h1>
          <button className={styles.button}>ボタン</button>
        </div>
      );
    };
    
    export default App;
    

    App.module.css

    .container {
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 20px;
    }
    
    .button {
      background-color: #007bff;
      color: #fff;
      padding: 10px 20px;
      border: none;
      cursor: pointer;
    }
    

    index.html

    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>CSS モジュール</title>
      <link rel="stylesheet" href="dist/bundle.css">
    </head>
    <body>
      <div id="root"></div>
      <script src="dist/bundle.js"></script>
    </body>
    </html>
    

    package.json

    {
      "name": "react-typescript-webpack-css-modules",
      "version": "1.0.0",
      "description": "React, TypeScript, Webpack を使用して CSS モジュールをインポートする例",
      "private": true,
      "scripts": {
        "start": "webpack-dev-server --config webpack.dev.config.js",
        "build": "webpack --config webpack.prod.config.js"
      },
      "dependencies": {
        "react": "^18.0.0",
        "react-dom": "^18.0.0",
        "typescript": "^4.8.4",
        "webpack": "^5.72.1",
        "webpack-cli": "^4.9.1",
        "webpack-dev-server": "^4.8.1",
        "css-loader": "^6.7.1",
        "style-loader": "^3.4.4"
      },
      "devDependencies": {
        "@types/node": "^18.0.0",
        "@types/react": "^18.0.15",
        "@types/react-dom": "^18.0.15",
        "ts-loader": "^9.3.1"
      }
    }
    

    webpack.config.js

    const path = require('path');
    const webpack = require('webpack');
    
    module.exports = {
      mode: 'development',
      entry: './src/App.tsx',
      output: {
        filename: 'dist/bundle.js',
        path: path.resolve(__dirname, 'dist'),
      },
      module: {
        rules: [
          {
            test: /\.tsx$/,
            use: [
              { loader: 'ts-loader', options: { transpileOnly: true } },
            ],
          },
          {
            test: /\.css$/,
            use: [
              { loader: 'style-loader' },
              { loader: 'css-loader', options: { modules: true } },
            ],
          },
        ],
      },
      resolve: {
        extensions: ['.tsx', '.ts', '.js'],
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin(),
      ],
      devServer: {
        hot: true,
        open: true,
      },
    };
    

    実行

    以下のコマンドを実行して、開発サーバーを起動します。

    npm start
    

    ブラウザで http://localhost:3000 にアクセスすると、CSS モジュールを使用してスタイル設定されたアプリケーションが表示されます。

    このサンプルコードは、React、




    CSS モジュールをインポートするその他の方法

    @emotion は、CSS モジュールと類似した機能を提供するライブラリです。@emotion を使用すると、コンポーネント内で CSS コードを直接記述できます。

    import React from 'react';
    import styled from '@emotion/styled';
    
    const Button = styled.button`
      background-color: #007bff;
      color: #fff;
      padding: 10px 20px;
      border: none;
      cursor: pointer;
    `;
    
    const App: React.FC = () => {
      return (
        <div>
          <h1>CSS モジュール</h1>
          <Button>ボタン</Button>
        </div>
      );
    };
    
    export default App;
    

    styled-components は、@emotion に似たライブラリです。styled-components を使用すると、コンポーネントをテンプレートリテラルを使用して作成できます。

    import React from 'react';
    import styled from 'styled-components';
    
    const Button = styled.button`
      background-color: ${(props) => props.color || '#007bff'};
      color: ${(props) => props.textColor || '#fff'};
      padding: 10px 20px;
      border: none;
      cursor: pointer;
    `;
    
    const App: React.FC = () => {
      return (
        <div>
          <h1>CSS モジュール</h1>
          <Button>ボタン</Button>
          <Button color="#ff0000" textColor="#fff">赤いボタン</Button>
        </div>
      );
    };
    
    export default App;
    

    CSS in JS は、CSS コードを JavaScript コード内に記述する手法です。これにより、CSS コードをコンポーネントと密接に関連付けることができます。

    import React from 'react';
    
    const Button = (props) => {
      const styles = {
        button: {
          backgroundColor: '#007bff',
          color: '#fff',
          padding: '10px 20px',
          border: 'none',
          cursor: 'pointer',
        },
      };
    
      return (
        <button style={styles.button}>
          {props.children}
        </button>
      );
    };
    
    const App: React.FC = () => {
      return (
        <div>
          <h1>CSS モジュール</h1>
          <Button>ボタン</Button>
        </div>
      );
    };
    
    export default App;
    

    これらの方法はそれぞれ長所と短所があります。

    • CSS モジュール: 汎用性が高く、多くのプロジェクトで使用されています。
    • @emotion: コンポーネント内で CSS コードを直接記述できるため、簡潔なコードを書くことができます。
    • styled-components: コンポーネントをテンプレートリテラルを使用して作成できるため、読みやすく、保守しやすいコードを書くことができます。
    • CSS in JS: CSS コードをコンポーネントと密接に関連付けることができます。

    reactjs typescript webpack


    JavaScriptとReactで直面する「Reactコンポーネントが状態変更で再レンダリングされない問題」:解決策と回避策

    この問題には、主に以下の3つの原因が考えられます。状態の参照渡し: setState メソッドでオブジェクトを直接更新する場合、Reactはオブジェクトが同じであるとみなして再レンダリングをスキップしてしまう可能性があります。不要な再レンダリング: すべてのコンポーネントが毎回再レンダリングされると、パフォーマンスが低下します。...


    componentDidMount を使用する利点

    React ドキュメントでは、AJAX によるデータフェッチは通常 componentDidMount ライフサイクルメソッド内で行うよう推奨されています。これは componentWillMount メソッドを使用するよりもいくつかの利点があるためです。...


    【保存版】TypeScriptで日付ソートの悩みを完全解決!豊富なサンプルコード付き

    日付が文字列として格納されている場合、Array. prototype. sort() メソッドは文字列を比較するため、正しい日付順序でソートされません。これを解決するには、ソート前に日付を Date オブジェクトに変換する必要があります。...


    3 つの主要な方法とその他のテクニックでマスターする TypeScript オブジェクト配列の反復処理

    このチュートリアルでは、TypeScript でオブジェクトの配列を反復処理する方法について説明します。 3 つの主要な方法と、それぞれの利点と欠点について説明します。for ループは、最も基本的な反復処理方法の一つです。 配列の各要素にアクセスするためにインデックスを使用します。...


    2 つの enum を 1 つにまとめる!TypeScript で enum をマージする方法を徹底解説

    最も簡単な方法は、新しい enum を作成し、マージしたい 2 つの enum の値をすべて含めることです。この方法の利点は、シンプルで分かりやすいことです。欠点は、すべての値を手で書き写さなければならないことです。型エイリアスを使用して、2 つの enum を 1 つの型として定義することができます。...