これまで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をブラウザで確認できる。
ファイルの編集に合わせてオートリロードしてくれるので毎回ビルドする必要がなくなる。
各人の役割
思いの他大所帯になってしまった。
JSXや特殊なCSSはそのままではブラウザで読めないので、webpackに渡してやる。
するとwebpackは各種ツール(BabelやPostCSSなど)にソースを渡すことで一般的な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ファイルがあれば良い。
自分が書くコードは
<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>
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
欄にコマンドを書いておくと一発で呼び出せるようになる。例えば
{
//...
"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の設定はここ。
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ファイルは
- postcssで独自関数やネストなどを変換
- css-loaderで*CSSモジュール *を変換
- style-loaderで変換したCSSを
<style>
タグに配置
という処理をしている。
babelrc
babelの設定はここ。
{
"presets": [
"@babel/preset-env",
"@babel/react"
]
}
Babelで使用するプリセットを選択。
@babel/prese-env
は大体のES記法を変換してくれる。@babel/react
でjsxなどのReactの文法を変換。
postcss.config.js
postcssの設定はここ。
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 />
とかにするとちょっとすごい。
エラーが出る箇所
やたらめったらプラグインを使ったので色んな所からエラーが出る。
- Node.jsとnpmはバージョンによる違いが結構ある。特にWindows版。
- npmで最新のnpmをインストール(
npm install npm
)して古いnpmを削除……みたいな方法とかややこしい
- npmで最新のnpmをインストール(
- まずWebpackはバージョン4を使っているので3以前の資料では異なる場合がある。 react-toolboxは依存関係のバージョンの警告が出たのでBeta版まで引き上げてみた。
- Babelやwebpackのエラーはメッセージを調べればそこそこ簡単にたどり着ける
- CSSはエラーがメッセージとして出ることが少ないので
stylelint
のようなCSSのLintツールも導入すればわかりやすいかもしれない。
まとめ
- npmから始まり、React、Babel、webpack、CSS、PostCSS等々の愉快な登場人物についての理解を深める必要があった。
- ちなみにReactはコマンド一発で環境を構築できるツールなんかもあるので手っ取り早くそれを使うのがいいんだろうか。
- 一応動くところまで環境を構築できたので、あとはポチポチReactのコンポーネントを配置していくだけでWEBアプリが作れそう。
参考文献
- react-toolbox
- 最新版で学ぶwebpack 4入門 - スタイルシート(CSSやSass)を取り込む方法 - ICS MEDIA
- CSSモジュール ― 明るい未来へようこそ | POSTD
- webpackでjsxファイルをJavaScriptにトランスパイルする - Qiita
- Reactで「Hello world」 – React入門 - to-R Media
- Create a New React App – React
- これからReactを勉強する人が最初に見るべきスライド7選 | UX MILK
- JSといえばjQueryだったWebデザイナーが、Reactを1年間使って感じたメリット | dwango creators' blog(ドワンゴクリエイターズブログ)
- 色を自在に変換するcolor-mod()関数 - CSSにおける色の指定方法 | CodeGrid