Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9100

React で eject せずに Scoped SASS (.scss) を使う

$
0
0

概要

  • scoped sass (ファイル内限定で適用されるスタイル) を使いたいでござる
  • でもnpm run ejectはしたくないでござる
  • cra-sassを導入するとかんたんにできるでござる

参考文献

実行環境

  • create-react-appで作った react project
    • 既存プロジェクトなのでversionわからん すまん
  • TypeScript

サンプルコード (変更前)

node-sassを入れてふつーにscssを使うとこうなる。

Sample.tsx

Sample.tsx
import*asReactfrom"react";import"./Sample.scss";exportconstSample:React.FC=()=>{return(<divclassName="outer">
      OUTER
      <divclassName="inner">INNER</div><ul>{["red","blue","green"].map((each,index)=>(<liclassName={each}key={index}>{each.toUpperCase()}</li>))}</ul></div>);};exportdefaultSample;

Sample.scss

Sample.scss
.outer{&,*{display:flex;flex-direction:column;padding:8px;border-left:1pxsolidgray;}font-size:1.2rem;.inner{font-weight:bold;}ul{li{&.red{color:red;}&.green{color:green;}&.blue{color:blue;}}}}

ビルド結果(html)

<divclass="outer">
  OUTER
  <divclass="inner">INNER</div><ul><liclass="red">RED</li><liclass="blue">BLUE</li><liclass="green">GREEN</li></ul></div>

実行結果

この実装の問題点

Sample.scss に記述したスタイルのscopeはグローバルである。
すなわち、Sample.tsx と同時にロードされるコンポーネントに、
同じclassName(例えば.outer)が割りあたっていると、互いに影響を受け合いバグの原因となる

解決策

閉じたscopeを扱うことのできるsass loaderを導入する

導入手順

cra-sass を導入

npm install --save-dev cra-sass

cra-sass を実行

$(npm bin)/cra-sass

するとなんかいっぱいインストールしてプロジェクトが魔改造される

package.json
@ devDependencies
+    "cra-sass": "0.0.5",

@ dependencies
+    "node-sass-chokidar": "^1.4.0",
+    "npm-add-script": "^1.1.0",
+    "npm-run-all": "^4.1.5",

@ scripts
-    "start": "react-scripts start",
-    "build": "react-scripts --max-old-space-size=2048 build",
+    "start": "npm-run-all -p watch-css start-js",
+    "build": "npm run build-css && react-scripts build",
     "test": "react-scripts test",
-    "eject": "react-scripts eject"
+    "eject": "react-scripts eject",
+    "build-css": "node-sass-chokidar src/ -o src/",
+    "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
+    "start-js": "react-scripts start"

--max-old-space-size=2048とか無くなってぶっ壊れてんじゃん!
ってことで無駄にぶっこわされたとこは直しておく

package.json
-    "build": "react-scripts --max-old-space-size=2048 build",
+    "build": "npm run build-css && react-scripts --max-old-space-size=2048 build",

サンプルコード(リファクタ後)

Sample.scss

Sample.module.scssに改名する

Sample.tsx

  • scssのimport
  • classNameの割当てのしかた

だけを変更

Sample.tsx
import*asReactfrom"react";importstylesfrom"./Sample.module.scss";exportconstSample:React.FC=()=>{return(<divclassName={styles.outer}>
      OUTER
      <divclassName={styles.inner}>INNER</div><ul>{["red","blue","green"].map((each,index)=>(<liclassName={styles[each]}key={index}>{each.toUpperCase()}</li>))}</ul></div>);};exportdefaultSample;

ビルド結果

<divclass="Sample_outer__144wv">
  OUTER
  <divclass="Sample_inner__EiBfI">INNER</div><ul><liclass="Sample_red__1ktYQ">RED</li><liclass="Sample_blue__32ZOZ">BLUE</li><liclass="Sample_green__2OrZU">GREEN</li></ul></div>
css部分の抜粋
.Sample_outer__144wv{font-size:1.2rem;}.Sample_outer__144wv,.Sample_outer__144wv*{display:flex;flex-direction:column;padding:8px;border-left:1pxsolidgray;}.Sample_outer__144wv.Sample_inner__EiBfI{font-weight:bold;}.Sample_outer__144wvulli.Sample_red__1ktYQ{color:red;}.Sample_outer__144wvulli.Sample_green__2OrZU{color:green;}.Sample_outer__144wvulli.Sample_blue__32ZOZ{color:blue;}

その他やったこと

scriptsが壊されてないかチェックしよう

start, build, test が、 cra-sass によって破壊されている恐れがある
特にdefaultから変更している場合注意しよう

.cssが.scssと同階層に出力されるようになってうっおとしい

  • node-sass-chokidar のしわざくさい
  • でもoutputしなくするオプションとかなさげ
  • めんどいから、別階層に吐かせて、ignoreすることにした
package.json
-    "build-css": "node-sass-chokidar src/ -o src/",
+    "build-css": "node-sass-chokidar src/ -o built-css/",
-    "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
+    "watch-css": "npm run build-css && node-sass-chokidar src/ -o built-css/ --watch --recursive",
.gitignore
+/built-css

node-sassをすでに使っていた場合、不要になる

npm r node-sass

おしまい

これで快適な React x Scoped SASS 生活が始まる


Viewing all articles
Browse latest Browse all 9100

Latest Images

Trending Articles