LoginSignup
2
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だったらいいなぁと思っています。

2
2
0

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
  3. You can use dark theme
What you can do with signing up
2
2