Webpack4でReactの環境構築。Create react appを使わずにReactアプリを作る。-2 -CSS, Sass, ESLint -
【所要時間】
7時間(2019年2月12日)
【概要】
- Reactの環境構築の続き。
- CSS, SCSS, ESLintの設定をする。
- https://github.com/astatsuya/webpackori(レポジトリ)
参考リンク
【要約・学んだこと】
ReactにCSSを適用する方法
手順として
- CSSをJavaScriptで読み込めるようにする。
- CSSデータをHTMLで読み込めるようにする。
があるようだ。1はみんなcss-loaderを使っているようなのでcss-loaderを使う。
2は参考リンク含めて色々みたところ、下記の2通りのやり方があるようだ。
- styele-loader:
DOMにCSSを<style>タグを使って挿入する。 - mini-css-extract-plugin:
CSSを別のファイルに抽出する。CSSを持つJSファイルごとにCSSファイルを作成し、CSSとSourceMapsのオンデマンドローディングをサポートする。
注意点は、参考リンクではextract-text-webpack-pluginが紹介されているが、ドキュメントによるとwebpack4ではmini-css-extract-pluginに変わった点。
どちらも一長一短らしいがよくわからないが、css-loaderのドキュメントがStyle-loaderだったので、こちらを使う。
その前にcssファイルの作成と、app.jsへのcssファイルの取り込みを行う。(app.jsのcomponent名がIndexとなっていたが、Appに変更。ファイル名と一致させた。)
// src/components/app.jsimport React from 'react';
import { hot } from 'react-hot-loader'
import Test from './test';
import Counter from './counter';
import styles from './app.css';const App = (props) => (
<div className={styles.app}>
<Counter />
<Test />
<h2>これはh2</h2>
<p>ここはIndex</p>
<p>ここはIndex</p>
<p>{props.text}</p>
</div>
);export default hot(module)(App);
cssファイルの作成
// src/components/app.css.app {
color: blue;
}p {
background-color: blue;
color: white;
}.app h2 {
color: brown;
}
css-loader, style-loaderのインストールと設定
yarn add -D css-loader style-loader
webpack.config.jsの設定。まずはオプションなどをせずにcssが適用できるかを確認。このstyle-loaderとcss-loaderの順番は重要。後半にあるものから処理されるらしく、逆にするとうまくいかない。
// webpack.config.js...module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader",
}
]
}
]
},...
最低限の設定をしたらyarn buildで確認。
スタイルが適用された。しかしクラス指定した部分がうまく適用されていない。
- css-loaderの設定
optionsの設定
- modules: これをtrueにすることによりcss Modulesとセットアップモードを可能にする。今回はstyles.appの記述法が適用された。
- localIndentName: 生成されるclassの名前を決める。初期だとよくわからないので、わかりやすく[name]_[local]_[hash:base64]にした。
これで狙い通りに表示された。
現在webpack.config.jsは下記のようになっている。
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path');
const webpack = require('webpack');const htmlPlugin = new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "./index.html"
});module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public'),
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: true,
localIdentName: "[name]_[local]_[hash:base64]",
}
}
]
}
]
},
performance: {
hints: false
},
plugins: [
htmlPlugin,
new webpack.HotModuleReplacementPlugin(),
]
};
sass-loaderの設定
実際は.scss形式でcssを適用する事が多くあると思うので、こちらも設定する。名前的にcss-loaderの仲間っぽいsass-loaderを使う。
yarn add -D sass-loader node-sass
Node Sassか Dart Sassというものも合わせて必要らしい。ここではnode-sassを使う。
まずはwebpack.config.jsの設定
...module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.(css|scss)$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: true,
localIdentName: "[name]_[local]_[hash:base64]",
}
},
{
loader:"sass-loader",
}
]
}
]
},...
続いてscssファイルの作成
// src/_styles.scss@mixin button {
button {
padding-left: 5px;
padding-top: 5px;
height: 30px;
width: 20%;
}
}$brown: rgb(180, 81, 81);
もう一つ。_styles.scssで作ったmixinをインポートする。また、入れ子でスタイルを指定する。これらはcssにはない機能。
@import '../styles';.app {
color: red;
p {
background-color: yellow;
color: red;
}
h2 {
color:$brown;
}
@include button;
}
これをapp.jsにインポートする。
import React from 'react';
import { hot } from 'react-hot-loader'
import Test from './test';
import Counter from './counter';
import styles from './appScss.scss';const App = (props) => (
<div className={styles.app}>
<Counter />
<Test />
<h2>これはh2</h2>
<p>ここはIndex</p>
<p>ここはIndex</p>
<p>{props.text}</p>
</div>
);export default hot(module)(App);
セーブするとこれらのscssファイルが画面に適用された。
今のところオプションで指定が必要な部分もなさそうなので、特に指定しない。
ESLintの設定
思えば最初にやるべきだった。
これもdependenciesが多いからややこしい。とりあえず今回作っているReactアプリの構文チェックを行うようにする。設定はまだ自分のやり方みたいなのはないので、air-bnb-styleに従う。
※ここはハマりポイントで、./node_modules/.bin/eslint --init
でuse-popular-styleを設定すると、./node_modules/.bin/eslint src
を実行する際にファイルやディレクトリが見つからないというエラーになる。なんでかはわからないけど昔もなった記憶がある。
まずは必要なdependenciesをインストール
yarn add -D eslint eslint-plugin-react eslint-config-airbnb
そして実行すると
./node_modules/.bin/eslint src
色々なdependenciesが足りないとエラーが出るので、インストール。
yarn add -D eslint-plugin-import eslint-plugin-jsx-a11y
そして改めて実行すると、スタイルチェックされているのがわかる。
自動で作成された.eslintrc.jsはこのようになっている。
.eslintrc.jsmodule.exports = {
“extends”: “airbnb”
};
proptypesを入れたり今エラーを修正するのは色々面倒(本来従うべき)なので、とりあえずreactの標準の設定に戻す。
"extends": [
"eslint:recommended",
"plugin:react/recommended"
]
今はimportがreservedされているという警告が出ているので、これを消す。
yarn add -D babel-eslint
これを.eslintrc.jsのparserに追加するとimportの警告は消えるが、documentとmoduleが定義されてないと出てくるので、.eslintrc.jsのglobal変数に追加する。
module.exports = {
// "extends": "airbnb"
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"parser": "babel-eslint",
"globals": {
"module": true,
"document": true,
}
};
これでエラーが消えた。
【わからなかったこと】
- css-loaderと同じような設定がstyle-loaderにあったが、違いがよくわからなかった。とりあえず機能しているので気にしない。
yarn buildすると
<script type=”text/javascript” src=”bundle.js”></script>
これが何度も追加されていく。これはbundleする際の設定変更で修正出来そうだが、疲れたのでまた今度確認。
【感想】
css-loader, style-loaderのインストールがなぜかうまく機能しなかった。(node_modulesとyarn.lockを消してインストールしたらうまくいった。)
今回もブラックボックスはかなりあるが、とりあえず機能するところまでいったのでよかった。
これでプロダクトを作る際に必要最低限な機能の環境構築はできたと思う。次回はprettierの設定等を追加して行きたい。