Help us understand the problem. What is going on with this article?

jQueryしかしてこなかったけどそろそろReactをやる

More than 1 year has passed since last update.

これまでDOMの操作はjQueryくらいしか使ってなかったのですが、頑張ってReactに手を出してみました。
備忘録的な意味合いが強いですが、自分のような初学者がReact周りの用語の意味をなんとなく掴むのには役立つかもしれないので記事にしてみました。

React?

  • 既に存在するDOM要素を操作する事に長けるjQueryと違って、動的にDOM要素を生成するときにも便利
    • 別にjQueryと一緒に使っても良い
  • jsxというテンプレート記法で書けばjsコード内にHTMLタグをほぼそのまま書ける
    • 当然そのままでは動かないのでjsコードに変換してやる必要はある
    • jsxの構文自体は簡単
  • jsxを変換したりする必要があるのでモジュールバンドラとかESコンパイラで自動的に変換しようぜ!
    • この辺からだんだん怪しくなってくる
    • webpackとBabelを使った
  • ReactはUIをコンポーネントにできる
    • UIのライブラリもたくさん
    • react-toolboxが使ってみたかったのもReact習得の動機の一つ

登場人物

現代のWEB開発は環境がややこしい。

React

主人公。Facebook生まれ。
動作させるには最低「react.js」と「react-dom.js」さえあればいい。

JSX

React用の記法。テンプレートエンジン的な。

var hoge = (<div>Hello, Mr. {name} </div>);

みたいな書き方が許される。
もちろんjsの記法だけでも以下のように

var hoge = React.createElement("div", null, "Hello", name)......

みたいな書き方もできなくはないけどそんなことするくらいならJSXで書いてjsに変換したほうが早いと思う。

JSXTransformer

配布されているJSXTransformer.jsを読み込めば、事前に変換しなくてもjsxファイルを読める。
手軽にHello world等を試すのに使える。
実際に動かすとなると後述のBabelなどで事前に変換するのが良いと思われる。

npm

Node.jsのパッケージマネージャ。Node.jsをインストールすればだいたいついてくる。
Reactや以下のBabelやWebpackをインストールでき、更にインストールされたライブラリのコマンドも打てるようになる。

Babel

"jsっぽい言語"(AltJS)のコンパイラ・トランスパイラ。
jsxみたいなjsっぽい言語のほか、ES(ECMA Script)等の「正規のjsだけど各ブラウザで未実装」みたいなのを「みんなが使えるちょっと古い時代のjs」に変換してくれる。
例えばES2015以前の(筆者が知っている)javascriptはクラスもアロー関数もないけれど、最近のESではちゃんと仕様が決まっているのでBabelで変換してしまえばクラスもアロー関数も書き放題。

Webpack

モジュールバンドラ。
モジュールバンドラは複数のjsファイルをまとめて一つのファイルにしてくれる。
クラスごとにファイルを分けたりしていても、Webpackで1個にまとめてしまえばサイトにアップロードするのが楽になる。おまけにHTTPの都合上複数ファイルがあるときより読み込みも早い。
更にWebpackはCSSやらフォントやらもまとめて一つにすることが可能。
各ファイルを読み込むときにローダーというプラグインを噛ませることができるので、例えばBabelでjsxを変換するみたいなこともまとめてできる。

似たようなものにbrowserifyやrollup、Gulpなどもあるけど、とりあえず今回はwebpackで話を進める。

react-toolbox

React用UIライブラリ。

(<div>
   <DatePicker />
</div>)

なんて書くだけで日付のピッカーを使えたりしてチョー便利。が、これを動かすまでがチョー大変だった。

CSS

ちょっと前はスタイルを記述するだけだったのが、最近はモジュール化がどうこうとかで公式・非公式含めていろんな仕様がある。

CSS Modules

CSSモジュール。別なファイルなら同じセレクタ名を命名しても、変換時に接頭辞をつけて衝突しないようにしてくれる。これでモジュール化がしやすくなるということらしい。
これの変換をしないとセレクタ名が衝突するので変換しよう。

Sass

今回は使っていない。
SASS形式とSCSS形式の2通りの書き方があるスタイルシート。CSSに変換して使う。
ネスト機能などもあるが、そういった機能は後述するPostCSSでも代用できる。

PostCSS

CSSのポストプロセッサ・プリプロセッサ。
いろんな機能が使用されたCSSを、各ブラウザが対応しているCSSに変換してくれる。
CSS内で変数を使ったり、CSSのネストができるようになったりする。(プリプロセス)
CSSに各ブラウザ用のプレフィックス(ベンダープレフィックス)を自動でつけてくれる機能もある(ポストプロセス)
名前の割に後処理以外にも事前処理も結構する。

CSS Color Module Level4

CSSの色に関する仕様。この機能がreact-toolboxには使用されているけどブラウザは未対応なのでPostCSSを使って変換してあげよう。

webpack-dev-server

npmライブラリ。サーバーを起動してwebpackでまとめたjsをブラウザで確認できる。
ファイルの編集に合わせてオートリロードしてくれるので毎回ビルドする必要がなくなる。

各人の役割

思いの他大所帯になってしまった。
react.png
JSXや特殊なCSSはそのままではブラウザで読めないので、webpackに渡してやる。
するとwebpackは各種ツール(BabelPostCSSなど)にソースを渡すことで一般的なjs・cssに変換する。
最終的に変換されたファイルをwebpackがひとまとめにして一つのjsに吐き出してくれる。
あとはwebpack-dev-serverでlocalhost上で確認したり、自分のサイトにアップしたりすればブラウザで見れるようになる。

ハローワールド

react-toolboxのボタンにHello worldと書いて配置してみる。
作業ディレクトリでnpm initと実行する。
npmはインストールしたパッケージを記録するpackage.jsonファイルが必要で、質問に答えていくことでそれを作成してくれるコマンド。
npm initしなくてもname、version、description要素が記述されたpackage.jsonという名前のJSONファイルがあれば良い。

自分が書くコードは

dist/index.html
<html>

<head>
  <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>

<body>
  <div id="app"></div>
</body>
<script src="./index.js"></script>

</html>
src/main.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import {Button} from 'react-toolbox/lib/button';
ReactDOM.render((
  <Button label="Hello World!" raised primary/>
), document.getElementById('app'));

これくらい。

パッケージの導入

上のコードを変換するのに使ったパッケージが

    "@babel/cli": "^7.1.2",
    "@babel/core": "^7.1.2",
    "@babel/preset-env": "^7.1.0",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.4",
    "css-loader": "^1.0.0",
    "postcss-color": "^1.0.1",
    "postcss-loader": "^3.0.0",
    "style-loader": "^0.23.1",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.9"
    "@babel/polyfill": "^7.0.0",
    "npm": "^6.4.1",
    "postcss": "^7.0.5",
    "postcss-calc": "^7.0.0",
    "postcss-preset-env": "^6.2.0",
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "react-toolbox": "^2.0.0-beta.13",

こんな感じ。

npm install @babel/cli @babel/core --Saveのようなコマンドで作業ディレクトリにパッケージがインストールされる。
 依存関係のバージョンがおかしかったりするとちゃんとエラーメッセージが出るのでその時は表示されたバージョンを指定してインストールする。
 Babelは新しいバージョンは@babelという名前になっていて、以前のバージョンのbabelパッケージもあるのでややこしい。
 〇〇-loader系のパッケージはwebpackのプラグイン。例えばcss-loaderはwebpackがcssをロードするときに使う。
 postcss-〇〇系はPostCSSのパッケージ。例えばpostcss-calcはCSS内でcalc()メソッドが使えるようになる。他にもpostcss-colorは色を変更するcolor()メソッドを標準のCSSでも実装されているrgb()メソッド等に置換してくれる。
react-toolboxは一部にcolor()calc()などのPostCSSのメソッドを使用しているのでそのままだとうまく反映されない。

各パッケージの設定

package.json

npmの設定はここに。
script欄にコマンドを書いておくと一発で呼び出せるようになる。例えば

package.json
{
  //...
  "scripts": {
    "build": "webpack",
    "start": "webpack-dev-server"
  },
  "dependencies": {
//...

としておけばnpm run buildでwebpackを、npm run startでwebpack-dev-serverを起動できる。
npm 5.2以上ならnpx webpack-dev-serverのように直接パッケージを実行することも可能。

webpack.config.js

webpackの設定はここ。

webpack.config.js
module.exports = {
  mode: "development",
  entry: `${__dirname}/src/main.jsx`,

  output: {
    path: `${__dirname}/dist`, // distディレクトリに出力
    filename: 'index.js'
  },
  // webpack-dev-serverの設定
  devServer: {
    contentBase: 'dist', // distディレクトリを起動
    open: true // 自動でブラウザを開く
  },

  module: {
    rules: [
      // JSXファイルはbabelに渡して変換してもらう
      {
        test: /\.jsx/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      // CSSはpostcss->css-loader->style-loaderの順に渡して変換してもらう
      {
        test: /\.css/,
        use: [
          'style-loader', // <style>タグに
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,  // SourceMapを生成してデバッグしやすくする
              importLoaders: 1, // css-loaderより前のローダの数(今回は1)
              modules: true,  // CSSモジュールに対応させる(大事)
            },
          },
          {
            loader: 'postcss-loader', // postcssの設定自体は別ファイル
            options: {
              sourceMap: true,
            }
          }
        ],
      },
      // Fonts
      {
        test: /\.(woff|eot|ttf)/,
        use: [
          'url-loader'
        ]
      }
    ]
  },

  resolve: {
    extensions: ['.js', '.jsx']
  },

  plugins: []
};

重要なのはmodule.rules以下。testの正規表現に当てはまるファイルをuseに指定したプラグインに渡す。
useが複数の場合は、後ろに書かれたプラグインから順に適用される。
特にCSSファイルは

  1. postcssで独自関数やネストなどを変換
  2. css-loaderで*CSSモジュール *を変換
  3. style-loaderで変換したCSSを<style>タグに配置

という処理をしている。

babelrc

babelの設定はここ。

babelrc
{
  "presets": [
    "@babel/preset-env",
    "@babel/react"
  ]
}

Babelで使用するプリセットを選択。
@babel/prese-envは大体のES記法を変換してくれる。@babel/reactでjsxなどのReactの文法を変換。

postcss.config.js

postcssの設定はここ。

postcss.config.js
module.exports = {
    plugins: [
        require('postcss-preset-env')({
            stage: 0, // 試験的な機能も含め変換
            features: {
                'custom-properties': {
                    preserve: false,  // カスタムプロパティを元の形式で保存しない
                },
                'color-mod-function': true, // color-mod()
            }
        }),
        require('postcss-calc'), // calc()
        require('postcss-color'), // color()
    ]
}

実行

npm run buildまたはnpx webpackでビルド。
src/フォルダのファイルがwebpackによっていろんなプラグインにたらい回されてdist/に出力される。
npm run startまたはnpx webpack-dev-serverでローカルにサーバーを立てて起動。
dist/index.htmlが開く。

うまく行けばボタンが表示される。うまく行かなければコンソールか、ブラウザの開発者コンソールにエラーがでているはず。

まぁちょっとこれだけだと労力に対して結果がショボい気もする。
でもほら、ボタンじゃなくて<DatePicker />とかにするとちょっとすごい。
NoName_2018-10-25_6-14-9_No-00.png

エラーが出る箇所

やたらめったらプラグインを使ったので色んな所からエラーが出る。

  • Node.jsとnpmはバージョンによる違いが結構ある。特にWindows版。
    • npmで最新のnpmをインストール(npm install npm)して古いnpmを削除……みたいな方法とかややこしい
  • まずWebpackはバージョン4を使っているので3以前の資料では異なる場合がある。 react-toolboxは依存関係のバージョンの警告が出たのでBeta版まで引き上げてみた。
    • よって公式よりGitHubを見たほうがわかりやすい。
    • PostCSS周りでreact-toolboxのGitHubには「color-mod()を使っている」的なことも書かれていたけどBetaではcolor()のほうが使われているような気がする。多分そういった変化がたくさんあるので都度調べる必要がある。
  • Babelやwebpackのエラーはメッセージを調べればそこそこ簡単にたどり着ける
  • CSSはエラーがメッセージとして出ることが少ないのでstylelintのようなCSSのLintツールも導入すればわかりやすいかもしれない。

まとめ

  • npmから始まり、React、Babel、webpack、CSS、PostCSS等々の愉快な登場人物についての理解を深める必要があった。
    • ちなみにReactはコマンド一発で環境を構築できるツールなんかもあるので手っ取り早くそれを使うのがいいんだろうか。
  • 一応動くところまで環境を構築できたので、あとはポチポチReactのコンポーネントを配置していくだけでWEBアプリが作れそう。

参考文献

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした