create-react-appとpugとstylus

その１
https://qiita.com/DaisukeNishi/items/dae74d5dcf5ddb171b3d
その２
https://qiita.com/DaisukeNishi/items/e93a3448668f65df7a91
その3
https://qiita.com/DaisukeNishi/items/697fb3579d7dd69324b3
その4
https://qiita.com/DaisukeNishi/items/801e1b1e02487e26e905
その6
https://qiita.com/DaisukeNishi/items/c8982546c803d2c5dc99

※これは５回目にあたります。

##create-react-app+pug+stylus簡単→そんな事なかった。
最初から`jsx`なんて書かない！俺は`pug`で全てやるんだと意気込んだが、

`pug`についての結論は、
逆にトランスパイル後の`jsx`の姿を想像できてないとツライだろうと思った。
なので、ある程度`jsx`の達人になってから`pug`でラクに見通せるようにする方が、
学習の順序としては近道だろう。

`CSS-Modules`についてすっごい調べたけど、`stylus-loader`のコンフィグを
`eject`しないでやろうとすると`customize-cra`にメソッドがなくて非公式プラグイン使ったり
`react-dev-utils`に書いてある処理や`extensions`の書き換えの所で
ハマるので、そっち方面で進めるのは、やめたほうが良いと思う。

`stylus`についてでた結論は、普通に`styled-jsx`使ったほうがラクだと思った。
Keita Ishibashi（usagi-f）さんも`styled-jsx`をオススメしてたし。
Githubのスターもそっちの方が多いし、ネットで解決案を探しやすい。


##目的
###で、この記事の目的とは？
・`React`を使いたい。
・`yarn eject`する選択肢はない。
・とにかく`pug`と`stylus`を使いたい。

それを、なんとかする記事です・・まぁ最初はなんとかなるんですよ。
「わーい、書けた書けた〜♪このまま行ける！」って思ったんですけど、

下記のやりかたを突き詰めていくと、結局`hash`された`CSS`にしたいなと思ったら
むしろ`yarn eject`した方がラクだし、`pug`のメリットを捨てなければいかんと思う。

なので今回この記事は、失敗を糧にしてもらう、というのと
`CSS-Modules`...?そんなものは知らんなぁ...という感じです。

##下準備
###必要なプラグインを揃える
`babel-plugin-〇〇`のいくつかのプラグインには
`devDependency`にしておくと動かないものがあるので`-D`を付けない事にしています（言い訳）

```shell
$ npm install -g create-react-app
$ create-react-app {yourProject}
$ cd {yourProject}

//基本セットと、「○○-loader」などを追加する
$ yarn add sass node-sass stylus pug
$ yarn add stylus-loader extract-text-webpack-plugin pug-loader json-loader

//babel系プラグインを追加する
$ yarn add babel-plugin-transform-react-pug
$ yarn add babel-plugin-transform-react-jsx

//（追記）→styled-jsxを使った方がいい。引き返すなら今ですよー！
$ yarn add styled-jsx
$ yarn add styled-jsx-plugin-stylus

//下記プラグインを使うと遠回りな気がする
$ yarn add babel-plugin-transform-jsx-css-modules
$ yarn add babel-plugin-react-pug-classnames
$ yarn add babel-plugin-react-css-modules

//eslint系プラグインを追加する
$ yarn add eslint-plugin-react-pug eslint-plugin-css-modules

//※overrideツールを追加する
$ yarn add react-app-rewired customize-cra customize-cra-add-stylus-loader
$ touch .eslintrc
$ touch .babelrc
```

###react-scriptsを取り出す
「いきなり何を言ってるんだ？結局直に`webpack.config.js`いじってるじゃん！」
と思うかもですが、直にいじるデメリットを軽減する方法を紹介しますのでご勘弁を。

`react-script`をホームディレクトリに複製し名前を（例：`react-scripts-pug-stylus`）とします。
適当で良いですが、公式パッケージや他のプロジェクトと混乱しない名前がよいです。

```
$ cp -r ./node_modules/react-scripts ../react-scripts-pug-stylus
$ cd ../react-scripts-pug-stylus
$ open ./config/webpack.config.js
```
`css-loader`や`sass-loader`は
`create-react-app`した時にデフォで用意されますが
そのままでは`stylus`が読み込めないので、`stylus-loader`を追加していきます。

```webpack.config.js
//（５０行目あたり）
const sassRegex = /\.(scss|sass)$/;
const stylRegex = /\.(styl)$/; //←追加
const sassModuleRegex = /\.module\.(scss|sass)$/;
const stylModuleRegex = /\.module\.(styl)$/; //←追加
```
sassの設定をコピーします。

```webpack.config.js
//（５００行目あたり）
 {
  test: sassRegex,
  exclude: sassModuleRegex,
  use: getStyleLoaders(
     {
       importLoaders: 3,
       sourceMap: isEnvProduction && shouldUseSourceMap,
     },
   'sass-loader'
 ),
 sideEffects: true,
},
//ここから下に追記をします。
{
  test: stylRegex,
  exclude: stylModuleRegex,
  use: getStyleLoaders(
    {
     importLoaders: 3,
     sourceMap: isEnvProduction && shouldUseSourceMap,
    },
  'stylus-loader'
 ),
 sideEffects: true,
},
```

```webpack.config.js
{
  test: sassModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 3,
      sourceMap: isEnvProduction && shouldUseSourceMap,
      modules: {
        getLocalIdent: getCSSModuleLocalIdent,
      },
    },
    'sass-loader'
  ),
},
//下に追加
{
  test: stylModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 3,
      sourceMap: isEnvProduction && shouldUseSourceMap,
      modules: {
        getLocalIdent: getCSSModuleLocalIdent,
      },
    },
    'stylus-loader'
  ),
},
```

あとは、ファイル拡張子の`extensions`に`.styl`を追加する。
別ファイルを参照するようになっています。

```webpack.config.js
//（300行目あたり）
extensions: paths.moduleFileExtensions
```
`path`って何？と思ったら、同じ階層に置いてある`path.js`です。

```path.js
const moduleFileExtensions = [
  'web.mjs',
  'mjs',
  'web.js',
  'js',
  'web.ts',
  'ts',
  'web.tsx',
  'tsx',
  'json',
  'web.jsx',
  'jsx',
  'styl' //←追加する
];
```
色々とプラグインを見てみたけど、これのスマートな代替策がない気がする。
純粋な`.styl`じゃなくても`.jsx`にした方が良いんじゃないかと後で思ったんですが、
それだと既存の資産を使えないので、、、このまま説明つづきます。

###.eslintrcを有効に

`customize-cra`でも書き換えできるのですが、
どうせ今`webpack.config.js`を書き換えてるんだし、もうここで書き換えちゃいます。

```webpack.config.js
//(370行目あたり)
useEslintrc: false, //←trueにする
```
ちなみに`customize-cra`でやるなら

```config-overrides.js
const { override,useEslintRc,disableEsLint} = require("customize-cra");
module.exports = override(
  useEslintRc(".eslintrc"),
  //disableEsLint()
);
```

###.babelrcを有効に

`customize-cra`でも書き換えできるのですが、
どうせ今`webpack.config.js`を書き換えてるんだし、もうここで書き換えちゃいます。

```webpack.config.js
//（２箇所ある）
babelrc: false, //←trueにする
```
ちなみに`customize-cra`でやるなら

```config-overrides.js
const { override,useBabelRc} = require("customize-cra");
module.exports = override(
  useBabelRc(".babelrc"),
);
```

###Githubに上げておく
`webpack.config.js`と`path.js`を編集し終わったら、
この`react-scripts-pug-stylus`を、ご自分で管理されている`Github`に上げてください。
（例）：https://github.com/daisuke240000/react-scripts-pug-stylus
※他人がカスタムした`react-scripts`を使っても動かないです。

```shell
$ cd ../yourProject
$ yarn remove react-scripts
```
###名前を変えて読み込む
保存する時には名前を変えたのですが、
オーバーライドツール（`react-app-rewired`など）を使用する場合、
元のパッケージの名前が`react-scripts`にしておかないと動かないので、下記のようにします。

プロトコルは`git+ssh://...`と書けるのですが、
開発環境の違いなどを考慮して`https://`の方が無難です。
（SourceTree使ってる人はsshでgitに接続しないため）

※下記の.json(.js)はシンタックスのハイライトのために付けているだけです。

```package.json.js
"react-scripts": "^3.4.0",// yarn removeで削除される
"react-scripts": "https://github.com/daisuke240000/react-scripts-pug-stylus",
// ↑追記する。パッケージ名を同じ名前にしておかないとオーバーライドできない。
// (中略)
// ↓「npm scripts」をこのように改変します。
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test --env=jsdom",
  "eject": "react-app-rewired eject"
},
```
変更を保存し、`package.lock.json`と`yarn.lock`を消して

```shell
$ yarn
```
パッケージを集めます。lockファイルが存在していると、書き直した時に見に行ってくれないです。
完了したらインストールされたパッケージ内容を確認。

```shell
$ open ./node_modules/react-scripts/config/webpack.config.js
```
成功ならば`stylus-loader`や`babelrc: true`になっています。
もしも更新されていなかったら、設定に失敗してると思いますので見直してください。
該当フォルダを削除し、lockファイルも削除し、`package.json`をもう一回確認して`$ yarn`です。

###.babelrcを編集
`react-pug`のクラス名の付け方に関しては`className`と`styleName`があります。
`CSS Modules`をやりたいので、最終的には`styleName`を使おうと思うのですが、

「本当に`styleName`で良いんだっけ？」と思ったので、
検証用でスイッチできるよう、両方書いて片方をコメントアウトしておきます。

↓（.js）はシンタックスハイライトのために付けてるだけです。

```.babelrc.js
{
  "presets": [
    "react-app"
  ],
  "plugins": [
    "transform-react-pug",
    // ["transform-react-pug",{"classAttribute": "styleName"}], //←あとで使います。
    // ["react-pug-classnames", {"classAttribute": "styleName"}],
    //["transform-jsx-css-modules", {"pathToStyles": "^\\.\\/module\\.scss$"}],
    "transform-react-jsx",
    "transform-jsx-css-modules",
    "react-css-modules"
  ]
}
```

###.eslintrcを編集
`$ eslint --init`で作成したものに、
`react-pug`と`plugin:react-pug/all`を追加するのが無難だと思います。
`$ eslint --init`できない？グローバルにインストールした方がいいかもです。

↓（.js）はシンタックスハイライトのために付けてるだけです。

```.eslintrc.js
{
  "env": {
    "es6": true,
    "node": true,
    "browser": true
  },
  "parserOptions": {
    "ecmaVersion": 6,
    "allowImportExportEverywhere": true
  },
  "plugins": [
    "react-pug" //←追加
  ],
  "extends": [
    "react-app",
    "plugin:react-pug/all" //←追加
  ],
  "rules": {
    "import/no-named-as-default": 0
  }
}
```

###config-overrides.jsを編集
上書きしているのに、ダメ押しで`react-app-rewired`を使います。
`customize-cra`と`customize-cra-add-stylus-loader`を使います。
設定ファイルはプロジェクト直下に`config-overrides.js`を作成します。

```shell
$ touch config-overrides.js
$ open config-overrides.js
```
####webpack設定上書き方法への考察：

#####オーバーライドツール、コレ１本で良いのでは？
`babel`や`eslint`に関する`webpack.config.js`のオーバーライドツールは
`react-app-rewired`だけを使えば良いのでは？と思ったのですが、
`.styl`や`stylus-loader`を追加するメソッドが、
非公式のプラグインしか見当たらないので、補助的に使う事にしました。

#####むしろ`react-app-rewired`は必要ないのでは？
むしろ逆に`react-app-rewired`は、使わなくて良いのではないか？とも思ったのですが、
`disableEsLint()`で`Eslint`を秒でオフにできるのは、とても使い勝手が良いですし、
そもそも`.styl`ファイルを読み込む事をやらないんだったら、こっちが王道です。

また、`react-scripts`のバージョンが上がるたびに改変リポジトリを作るのも不自由・非効率ですし、
できる事なら`react-app-rewired`と`customize-cra`にまとめられたらいいなと思っているので、
今回は、両方使ってみる事にしました。

このツールだけで、ほとんどオーバーライドする事が可能ですが、
独自の書き方を調べるのは若干面倒です。また、このやり方で`stylus`をよませる関連ネットに例文転がってないので、
誰もやってないような気がします。
特に`addStylusLoader`っていう、個人が作ってる拡張は、ぜんぜん使ってる人いない。

#####customize-cra+add-stylus-loaderを使ってる人が・・2人？
https://github.com/kingyinliang/cra-react/blob/7bb2df8a033732ac22e4c8726da8427378d411f3/config-overrides.js
https://github.com/zhzxang/tft-help/blob/5e5d1a1638fb0797c747227b8a08843c374025d2/config-overrides.js
世界で2人だけって・・何か、別のやり方があるんだろうと思います。

```config-overrides.js
const { override,
  //addBabelPlugins,
  //useBabelRc,
  //useEslintRc,
  disableEsLint
} = require("customize-cra");
const addStylusLoader = require('customize-cra-add-stylus-loader');

module.exports = override(
  //...addBabelPlugins(         //←使うと、babelのプラグインを追加できます。
    // "babel-plugin-transform-react-pug",
    // ["babel-plugin-transform-react-pug",{"classAttribute": "styleName"}],
    // ["react-pug-classnames", {"classAttribute": "styleName"}],
    // "babel-plugin-react-css-modules",
    // "babel-plugin-transform-react-jsx"
  //),
  //useBabelRc(".babelrc"),
  //useEslintRc(".eslintrc"), //←使うと.eslintrcが有効になります。
  //addStylusLoader(          //←使うとstylus-loaderの設定できるようです。※ネットに例文がない
    //{
    //}
  //),
  disableEsLint()        //←.eslintをオフにします。
);
```

##表示される部分を編集
###css、scss、stylは正しく読み込まれているのか検証する
複製したり変換したりして、App.cssを色々な形に変換しておく。

####検証時にハイフンがめんどうになる問題
class名にハイフン使えないって、
まったく「ナンノコッチャ」だとは思いますが・・

本番で使わないけど、検証の途中で`div(className=App-header)`
という風な、ちょっと`pug`らしくない書き方をした場合に、
ハイフン（-）が別の意味になってしまいます。

それで変につまづかないように、
ここでは、あらかじめハイフン（-）を何か他の書き方にしておきます。
※普通はclass名はハイフン推奨です。
※pugでハイフンを使うとバグる（引き算としての処理になる）ので
むしろ`div(className=A-B)`みたいな書き方は絶対できません。

```App.js
//（※以下、抜粋です）
//<header className="App-header">
<header className="AppHeader">
//<img src={logo} className="App-logo" alt="logo" />
<img src={logo} className="AppLogo" alt="logo" />
//<a className="App-link" >
<a className="AppLink" >
```

```App.css
/*App-logo {...}*/ 
.AppLogo {...}
/*App-header {...}*/
.AppHeader {...}
/*App-link {...}*/
.AppLink {...}
```

`create-react-app`の公式のドキュメントには
「もし`CSS Modules`を使うなら、ファイル名を`○○.module.css`にしなさい。」
と書いてある。（もうね、いろんな人がいろんな仕様いうからこんがらがってしまう）

```shell
$ cp App.css App.scss
$ cp App.css App.styl
$ cp App.css App.module.styl
```
`ｓcss`も`stylus`も、変換して中身を変えなくても動くはずです。
（※もし`sugarss`で解析できなかったら、正しい`stylus`の文法に書き換えてください）

`App.js`で、一個ずつコメントアウトをはずしながら確認を行なう。

```App.js
import React from 'react';
import logo from './logo.svg';
// 原型
import './App.css';
// import './App.scss';
// import './App.styl';
// import styles from App.module.styl 
```

`html`にあたる部分は`pug`に置き換えますが、
`pug`をトランスパイルする前に間違っているのか、
`pug`にトランスパイルした後に間違っているのか、
`ESLint`の設定ミスなのか、最初は分からないので、
`$yarn start`でサーブしながらチェックしていきます。

あと、ここで`disableEsLint()`をしておく方が問題の切り分けはできるかもです。

###初期状態
まずは、クラス名だけ書き換えた状態で動いているのを見ておく。

```App.js
import './App.css';
//（中略）
function App() {
  return (
    <div className="App">
      <header className="AppHeader">
        <img src={logo} className="AppLogo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="AppLink"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}
```
まあコレは、当然動くでしょう。（古いブラウザじゃなかったら。。）
###名前付きで読み込みしたパターンも書いてみる。

`styleName`は一旦使用せず、`className`でいく場合、
`import styles from './App.module.scss';`のような感じで、
外部ファイルを`styles`として読み込み、`className`の頭に`styles.`をつける。

`className`の値を囲んでいる`""`を消し、`{}`にしておく。
`"{}"`でも動くけど、`pug`で書いた時に全文がJS扱いになるので、`""`で囲んであると動かない。

```App.js
import styles from './App.module.styl';
//（中略）
function App() {
  return (
    <div className={styles.App}>
      <header className={styles.AppHeader}>
        <img src={logo} className={styles.AppLogo} alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className={styles.AppLink}
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}
```
これも動くっぽい。`pug`を`jsx`にトランスパイルした後、
こんな感じになってるんだろうな、というイメージ。

###htmlタグをpugに置きかえる
`pug`で書くけど、まだ`styleName`は使わない。
全部JSで処理するので`{}`などは不要です。`-`あるとバグるって言ってたのココです。

```App.js
import styles from './App.module.scss';
//（中略）
function App() {
  return pug`
    div(className=styles.App)
      header(className=styles.AppHeader)
        img(className=styles.AppLogo src=logo alt="logo")
        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a(className=styles.AppLink href="https://reactjs.org" target="_blank" rel="noOpener noReferrer")
          | Learn React
  `;
}
```

もしここで`Pug is not defined.`とでた場合は、
`babel-plugin-transform-react-pug`が読み込まれてないか、
プラグインの順番が前後逆になっていると思います。
`pug`を変換するのが先です。

###pug+styleNameの書き方

####まずはmoduleナシに戻す
`pug`+`styleName`を使う前に、まず`styles`を宣言してない状態に戻します。

```App.js
import './App.styl';
//（中略）
function App() {
  return pug`
    div(className="App")
      header(className="AppHeader")
        img(className="AppLogo"
          src=logo
          alt="logo")

        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a(className="AppLink"
          href="https://reactjs.org"
          target="_blank"
          rel="noOpener noReferrer")
          | Learn React
  `;
}
```
これは（あれ？一回説明したような気が）
ほぼ`<>`が消えただけで、トランスパイル後も形はあまり変わらないので、
問題なく動くと思います。

####pugらしい書き方をする
`pug`の場合、`div.App`（または`div`も省略して`.App`）というような書き方をします。
さらに`pug`っぽい記述にします。

```App.js
import './App.styl';
//（中略）
function App() {
  return pug`
    div.App
      header.AppHeader
        img.AppLogo(src=logo alt="logo")

        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a.AppLink(
          href="https://reactjs.org"
          target="_blank"
          rel="noOpener noReferrer" )
          | Learn React
  `;
}
```
問題なく動いている（気がする。眠くてよう確認してないけど）
これは`.App`を`className="App"`にトランスパイルしている。
あとはモジュール化するだけなので`className`の設定を`styleName`に変えれば行けるはず。

###※ご注意：ここから先、だんだんと泥沼にハマっていきます。


###pugでCSS Modulesどうやる？
このプラグインの説明によると`pug`で`CSS Modules`する時は、
class属性を`styleName`とするらしい。
https://github.com/pugjs/babel-plugin-transform-react-pug#css-modules
そういうズバリな変換機能がありそうだな〜。夢がひろがる。

----
ここ大事なので、雰囲気で英語をよまずに、ちゃんと意味を理解して翻訳してみよう。
###CSS Modules
（方法１）Babelを使用してJSX専用のCSSモジュール（例：babel-plugin-react-css-modules）をオンにするか、
（方法２）webpack-loaderを使用してスタイルをキー値オブジェクトに変換するかどうかは、pugで使用できます。

####方法１
・「Babel-plugin-react-css-modules」を使用して、
classAttributeオプションをstyleName値に設定する必要があります。

```babelrc.js
{
  "plugins": [
    ["transform-react-pug", {
      "classAttribute": "styleName"
    }]
  ]
}
```
```App.js
import './styles.css' // .hello{color:red}

const withCorrectStyles = pug`
  div.hello I am a red text
`
```
実際にやってみたが、

```.babelrc.js
"react-css-modules",
["transform-react-pug",{"classAttribute": "styleName"}],
```

`Cannot use styleName attribute for style name 'App' without importing at least one stylesheet.`
少なくとも1つのスタイルシートをインポートしないと、スタイル名「App」に`styleName`属性を使用できません。

→ん〜`stylus`を`stylesheet`だと認識してない。`css`とか`scss`じゃないと読み込んでくれないんだろうか。

####違うモジュールのドキュメントをよくよむ
`react-css-modules`で`.styl`のシンタックスを理解させるには・・・
これにオプションの設定をしておく必要がありそう。
https://www.npmjs.com/package/babel-plugin-react-css-modules

```.babelrc
["react-css-modules", {
   "filetypes" : {
      ".styl" : {
          "syntax" : "sugarss"
      }
  }
}],
```
`sugarss`というのが必要になってくる

```
$yarn add sugarss
```
あ、これでエラーが消え、ページを読み込めるようにはなった。
でも肝心のスタイルがあたらない。んがが・・

ハッシュされた名前を正しく取得するやり方がありそう。
`getLocalIdent`的な関数があったと思うので、そこをちゃんと見直してみるか・・？
いや、ちょっとこのやり方で時間の消費もったいないし、他の方法をためしてみよう。
（方法１については、まだ続きを書けそうな気がする。）


####方法2
・stylesをObjectに変換するwebpack-loader、またはその他のアプローチ

```App.js
import classes from './styles.css' // .hello{color:green}

const withCorrectStyles = pug`
  div(className=classes.hello) I am a green text
`
```
ここで「`classAttribute`」オプションを「`styleName`」値に設定し、
「`babel-plugin-transform-jsx-css-modules`」を追加することにより、開発体験を改善できます。

```.babelrc.js
{
  "plugins": [
    ["transform-react-pug", {
      "classAttribute": "styleName"
    }],
    "transform-jsx-css-modules"
  ]
}
```
ということなので、ドキュメントに近いソースを用意しておきます。

```App.js
import styles from './App.module.styl';
function App() {
  return pug`
    div(className=styles.App)
      header(className=styles.AppHeader)
        img(className=styles.AppLogo src=logo alt="logo")
        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a(className=styles.AppLink href="https://reactjs.org" target="_blank" rel="noOpener noReferrer")
          | Learn React
  `;
}
```
babelrcも上記のように書き換えておきます。（ここまでは、動く）

----
公式から開発体験を改善できる、と言われている
`babel-plugin-transform-jsx-css-modules`の英語を、実装前によく読んでおこう。

###babel-plugin-transform-jsx-css-modules
JSXのclassName属性を変換して、css-modulesの参照を取得します。
注：プロジェクトでCSSモジュールを有効にするのではなく、
自分で作成したと仮定します（たとえば、webpackやcss-loaderを使用して）。
（※うーん、よく読もうと思ったが、途中なんのこっちゃわからん）

####Example（例）

```app.js
import './styles.css'
 
const Component = () => (
  <div styleName="root">
    <h1 className="paragraph">Hello World</h1>
    <p className="global" styleName="local">I'm an example!</p>
  </div>
)
```
↓こんな感じでトランスパイルされるでしょう

```app.js
import __CSSM__ from './styles.css'
 
const Component = () => (
  <div className={__CSSM__['root']}>
    <h1 className="paragraph">Hello World</h1>
    <p className={["global", __CSSM__["local"]].join(" ")}>I'm an example!</p>
  </div>
)
```

/%\\.\\/module\\.scss$/に設定すると、。/ module.scssで開始および終了するimportを処理します。

```babelrc.js
{
  "plugins": [
    ["transform-jsx-css-modules", {
      "pathToStyles": "^\\.\\/module\\.scss$"
    }]
  ]
}
```

```
import './module.scss'
```
↓こんな感じでトランスパイルされるでしょう

```
import __CSSM__ from './module.scss'
```
----

翻訳をおわります。
つまり・・？これで、名前付きでimportしなくても、scopedなCSSができるっつーことですかね？
もう一回ソース見直してみます。

```App.js
import './App.styl';
function App() {
  return pug`
    div(className="App")
      header(className="AppHeader")
        img(className="AppLogo" src=logo alt="logo")
        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a(className="AppLink" href="https://reactjs.org" target="_blank" rel="noOpener noReferrer")
          | Learn React
  `;
}
```
↓コンパイルできてる状態。じゃあ、これはどうなんだろか？できるんじゃないか？
↓

```App.js
import './App.styl';
function App() {
  return pug`
    div(styleName="App")
      header(styleName="AppHeader")
        img(styleName="AppLogo" src=logo alt="logo")
        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a(styleName="AppLink" href="https://reactjs.org" target="_blank" rel="noOpener noReferrer")
          | Learn React
  `;
}
```

・・・できませんでした。エラーを読みます。
`React does not recognize the styleName prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase stylename instead.`

```App.js
import './App.styl';
function App() {
  return pug`
    .App
      header.AppHeader
        img.AppLogo(src=logo alt="logo")
        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a.AppLink(href="https://reactjs.org" target="_blank" rel="noOpener noReferrer")
          | Learn React
  `;
}
```
・・・トランスパイル後がエラーでてるんだから、当然トランスパイル前も同じでしょう。。。
`React does not recognize the styleName prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase stylename instead.`

###ご注意：ここから先は、さらに、とてもハマります
`React does not recognize the styleName prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase stylename instead.`
「styleNameを認識できません。もしDOMのカスタム属性として使いたいなら、stylenameにしてください。」

...もしかして、こういう事？

```.babelrc.json
["transform-react-pug",{
  "classAttribute": "stylename"
}],
```


####全然違いました。
`<div stylename="App">`
コレ、全然jsxとして機能しない。ただのhtmlのカスタム属性だった。この先エラーから辿れなくなって、キツイ。

####追加でReactにstyleNameを認識させるプラグインが必要かもしれない。

多分、コレかな。
https://www.npmjs.com/package/babel-plugin-react-pug-classnames
`React-pug`のサブコンポーネントを呼び出す問題を解決します。
（https://github.com/ezhlobo/babel-plugin-transform-jsx-classname-componentsの改良バージョン）

----
ここ、英語の説明をちゃんと読むべきだと思う。
####babel-plugin-react-pug-classnames：
また、className（styleName）の配列またはオブジェクト値を自動的に解析し、
classnamesのような関数を介して変換します。
すべてのクラス名にエレメント名を自動的にプレフィックスすることにより、BEMタイプの修飾子の命名を追加します。

（ん〜〜〜〜これはどうなんだろう。BEMタイプの修飾子を追加？いやはやstyleNameを認識させたいだけなんやけど）


###まず.babelrcの設定を変更する
初期設定時にコメントアウトしていた設定を使います。
`["transform-react-pug",{"classAttribute": "styleName"}],`
`["react-pug-classnames", {"classAttribute": "styleName"}],`
これで`Webpack`が認識できない属性を追加してあげれる、とおもう。

```.babelrc.js
{
  "presets": [
    "react-app"
  ],
  "plugins": [
    //"transform-react-pug",//←コッチをコメントアウトする
    ["transform-react-pug",{"classAttribute": "styleName"}],
    ["react-pug-classnames", {"classAttribute": "styleName"}],
    //"transform-react-jsx",//←いらないのかな。。
    "transform-jsx-css-modules"
  ]
}
```
？エラーが出てしまう

```
ReferenceError: div is not defined
```
なんだコレは、エラー出ないどころか、重症化してしまって、
pugの中身が正しく変換してない。


###ダメだ‥何度やってもここから先の手がかりがない
stackoverflowを漁っても、流石にこれじゃ検索のしようがない。
→ハマってしまったので、次の投稿にしようかと思います。
プラグインの順番か相性かどっちかな。
`CSS Modules`への道は遠い

##できたことはできたよ、オススメはせんけど

しかしコレで`pug`と`stylus`を使って書けるようになります。
最終的に、`styleName`使わないなら、まあ動くよ、というApp.jsはこんな感じでした。
`styleName`だけ切り分けてテストしてみないと原因特定できないや。まあそれは今度

```App.js
import React from 'react';
import logo from './logo.svg';
import './App.styl';
function App() {
  return pug`
    div.App
      header.AppHeader
        img.AppLogo(src=logo alt="logo")

        p
          | Edit 
          code src/App.js
          |  and save to reload.

        a.AppLink(
          href="https://reactjs.org"
          target="_blank"
          rel="noOpener noReferrer")
          | Learn React
  `;
}
export default App;
```
最終的なstylusはこのような感じ

```App.styl
.App
  text-align center

.AppLogo
  height 40vmin
  pointer-events none

@media (prefers-reduced-motion: no-preference)
  .AppLogo
    animation App-logo-spin infinite 20s linear

  .AppHeader
    background-color #282c34
    min-height 100vh
    display flex
    flex-direction column
    align-items center
    justify-content center
    font-size calc(10px + 2vmin)
    color white

.AppLink
  color #61dafb

@keyframes App-logo-spin{
  from{
    transform rotate(0deg)
  }
  to{
    transform rotate(360deg)
  }
}
```
最終的な.babelrcはこんな感じ。

```.babelrc.js
{
  "presets": [
    "react-app"
  ],
  "plugins": [
    "transform-react-pug",
    //["transform-react-pug",{"classAttribute": "styleName"}],
    //["react-pug-classnames", {"classAttribute": "styleName"}],
    "transform-react-jsx",
    "transform-jsx-css-modules"
  ]
}
```

最終的な.eslintrc.jsはこんな感じ

```.eslintrc
{
  "env": {
    "es6": true,
    "node": true,
    "browser": true
  },
  "parserOptions": {
    "ecmaVersion": 6,
    "allowImportExportEverywhere": true
  },
  "plugins": [
    "react-pug"
  ],
    "extends": [
    "react-app",
    "plugin:react-pug/all"
  ],
  "rules": {
    "import/no-named-as-default": 0
  }
}
```
config-overrides.jsはこんな感じ

```config-overrides.js
const { override, disableEsLint } = require("customize-cra");
module.exports = override(
  //useBabelRc(".babelrc"),
  //useEslintRc(".eslintrc"),
  disableEsLint()
);
```
ここに書いた方がいい設定と、`.babelrc`などに書いた方が良い設定の判断はつきませんが
プラグインは`.babelrc`に書いたほうが分かりやすかったです。

最終的なpackage.jsonはこちら。

```package.json
{
  "name": "sample",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "babel-plugin-react-css-modules": "^5.2.6",
    "babel-plugin-react-pug-classnames": "^0.3.1",
    "babel-plugin-transform-jsx-css-modules": "^1.0.0",
    "babel-plugin-transform-react-jsx": "^6.24.1",
    "babel-plugin-transform-react-pug": "^7.0.1",
    "customize-cra": "^0.9.1",
    "eslint-plugin-css-modules": "^2.11.0",
    "eslint-plugin-react-pug": "^0.8.4",
    "node-sass": "^4.13.1",
    "react": "^16.13.0",
    "react-app-rewired": "^2.1.5",
    "react-dom": "^16.13.0",
    "react-scripts": "https://github.com/daisuke240000/react-scripts-pug-stylus",
    "stylus": "^0.54.7",
    "stylus-loader": "^3.0.2"
  },
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test --env=jsdom",
    "eject": "react-app-rewired eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
```

###styleName…
ネットで調べても調べてもこの問題は解決しないので、
`styleName`とかもう死んだ規格なんじゃないかと思っています。
`styleName`に関するリンクをココにはる予定。
　↓
https://qiita.com/DaisukeNishi/items/617b7f9b4dde0bdeb3b9
（※ただの愚痴を貼っただけになってしまった）

###参考資料
https://html5beta.com/tools/css2stylus.html
https://github.com/dehimer/customize-cra-add-stylus-loader
https://github.com/arackaf/customize-cra/pull/144
adjustStyleLoadersの機能はありそうですが、使い方がわからない。
https://github.com/arackaf/customize-cra/blob/master/api.md#adjuststyleloaderscallback

---
https://github.com/timarney/react-app-rewired
https://github.com/gajus/babel-plugin-react-css-modules/issues/41
https://qiita.com/yikeda6616/items/0e31a920d533d70c0bd9
https://github.com/webpack-contrib/css-loader/issues/877
https://github.com/webpack/webpack/issues/8973
https://github.com/facebook/create-react-app/issues/5113
https://laracasts.com/discuss/channels/elixir/babel-plugin-react-css-modules-not-transforming-stylename-in-react
https://github.com/arackaf/customize-cra#with-webpack
https://github.com/timarney/react-app-rewired/issues/348
https://github.com/pugjs/babel-plugin-transform-react-pug#classattribute
https://github.com/timarney/react-app-rewired

---
http://www.beguru.work/2019/01/06/create-react-app-%E3%81%A7-babelrc%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B/
https://kic-yuuki.hatenablog.com/entry/2019/09/08/111817
https://github.com/facebook/create-react-app

---
https://stackoverflow.com/questions/56513346/how-to-use-pug-templating-engine-with-reactjs
https://qiita.com/TakuyaHara/items/f560d34aaa7857b32c82
https://www.npmjs.com/package/babel-plugin-transform-react-pug
https://github.com/pugjs/babel-plugin-transform-react-pug#eslint-integration
https://github.com/ezhlobo/eslint-plugin-react-pug
https://html2pug.now.sh/