LoginSignup
2

More than 3 years have passed since last update.

SCSSとstyled-componentsの勉強と比較のための環境を作った

Posted at

Make IT Advent Calendar 2019 24日目の記事です。

今年も危うくクリぼっちになりかけましたが、サークルの仲間とクリパすることになりました。
皆様も良いクリスマスをお過ごしください。

今年は、マイCSSブーム到来というやつです。5日目にもCSS関連の記事を投稿しました。
ゼミやインターンでSCSSを使っていますが、少し前からstyled-componentsに興味が湧いたので、勉強がてらどっちも書いてみようという旨です。

差分が発生する箇所について、コードを書いた感想を述べていくだけですので、実行環境だけ欲しい方は 環境 > リポジトリ(github) をクリックして git clone してください。

環境

  • リポジトリ(github)
    • 投稿時現在では、矢印アイコン・メニューボタン・クレジットカードコンポーネント(作り途中)が含まれています。
  • 言語・ライブラリ
    • typescript(v3.7.2)
    • react(v16.12.0)
    • storybook/react(v5.2.8)
    • scss(v4.13.0)
    • styled-components(v4.4.1)
  • 実行環境
    • macbook pro 2015 catalina
    • google chrome
  • エディタ
    • visual studio code
  • vscode plugin
    • vscode-styled-components
      • テンプレートリテラル内でcssの補完が効きます
    • color highlight(他にオススメあればご教授ください)
      • テンプレートリテラル内でカラーコードの背景に色が出なかったので導入しました

差分

webpack.config.js

SCSS
module.exports = {
  /* 一部省略 */
  module: {
    rules: [
      {
        test: /\.(ts|tsx)?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env", "@babel/react"]
            }
          },
          "ts-loader"
        ]
      },
      {
        test: /\.css?$/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.scss?$/,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              url: false,
              sourceMap: true,
              importLoaders: 2,
              modules: true
            }
          },
          {
            loader: "postcss-loader",
            options: {
              sourceMap: true,
              plugins: [require("autoprefixer")({ grid: true })]
            }
          },
          {
            loader: "sass-loader",
            options: {
              sourceMap: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new TypedCssModulesPlugin({
      globPattern: "src/**/*.scss"
    })
  ],
  /* 一部省略 */
};

scssのために4つのloaderを通しています。おかげでconfigが縦に長い!
autoprefixerしか使っていないので良いですが、今後を考えるとpostcss.config.jsとして別ファイルにした方が良いですね。

TypedCssModulesPlugin はscss保存時、自動でd.tsを生成します。dropbox製というのが好きです。

私は、フォルダをコンポーネント名にして、中にindex.tsxを作成する方法を使います。
これは、コンポーネントに関係する style.scss, style.d.ts, react custom hooksをまとめてフォルダ内に置けるので気に入っています。

styled-components
module.exports = {
  /* 一部省略 */
  module: {
    rules: [
      {
        test: /\.(ts|tsx)?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env", "@babel/react"],
              plugins: ["babel-plugin-styled-components"]
            }
          },
          "ts-loader"
        ]
      }
    ]
  },
  /* 一部省略 */
};

スッキリしました。
autoprefixer・TypedCssModulesPluginの役割は、styled-componentsが全て担ってくれます。
babel-plugin-styled-components について、こちらの記事が参考になりました。

reset.css

// for SCSS
import 'reset-css';

// for styled-components
import React from 'react';
import { Reset } from 'styled-reset';

const App = () => (
  <>
    <Reset />
    <div>Hello world!</div>
  </>
);

SCSSでは shannonmoeller/reset-css を使用します。
styled-componentsでは zacanger/styled-reset を使用します。

ソースコード比較(buttonコンポーネント)

See the Pen menu button scss by haduki1208 (@haduki1208) on CodePen.

マウスホバーでアニメーションするボタンです。
これをstyled-componentsで置き換えます。

See the Pen menu button styled by haduki1208 (@haduki1208) on CodePen.

scssがなくなったことでフォルダ内がスッキリしますが、scssの内容がtsxに移動するのでファイルが縦に長くなります。
私はvscodeのエディタを分割してtsxとscssを並べながらコードを書くので、辛さがあります。
↓こんな感じ
Image from Gyazo

解決策として、
1. atomic designを意識してコンポーネントを小さくしていく
2. style.tsx のようなファイルを用意してstyledの要素を宣言する
を考えました。基本的に1番の方法を実践していきたいと思います。

おわりに

趣味で何かコーディングするとき、このリポジトリ(github)を使っていこうかなと思っています。
storybookも始めて導入してみたのですが、どんなコンポーネントがあるか一通り見れるので便利です。

scss(css)で培ってきた技術がそのままstyled-componentsに活用できるため、
新規プロジェクトはstyled-componentsだったらいいなぁと思っています。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2