目的
Reactとは何ぞやという概念的な記事や実際の書き方を説明した記事は多い。
しかし、Reactでアプリケーション開発を実際にするにあたって具体的にどうすればいいのかという情報は断片的で初心者には全体像が掴めない。
例えば、モジュールバンドラーが必要だと知っている人は、webpackを設定する記事を調べれば分かるが、そもそもReactの開発環境の構築にそれが必要だと知らなければその記事にたどり着くことはできない。
Reactというフレームワークをインストールしさえば動かせるというものではなく、また動いたとしても実際の開発ではflowやeslintを使うことが多い。実際の開発環境は様々なライブラリが協働しているのが常である。
これらの背景を踏まえて、この記事では
Reactの開発環境を実際に0から構築する過程を通じて、開発環境では何が使われているかという全体像と、
それらの設定はどうすればいいかを経験的に理解すること
を目的としている。
したがって、全体像の構成要素ごとに詳細な説明はしない。むしろ掘り下げる必要性自体に気づくことを目指している。
全体の流れとしては、
- Node.jsのインストール
- Yarnの使い方
- webpackの設定
- Babelの設定
- Reactのインストール
- eslintの設定
- flowの設定
について順を追って説明する。
環境
利用したバージョン
> node -v
v8.11.1
> yarn info webpack version
4.7.0
> yarn info eslint version
5.0.0-alpha.2
> yarn info flow-bin version
0.71.0
ファイル構成
react-experiment
│ .babelrc
│ .eslintrc
│ .flowconfig
│ .node-version
│ package.json
│ webpack.config.js
│ yarn.lock
└─ src
─ index.js
─ sub.js
└─ dist
─ bundle.js
─ index.html
Node.jsのインストールとバージョン指定
Node.jsとは
- JavaScriptをサーバーサイドで実行するための環境
- パッケージのインストール、ビルド、テストなどの実行環境としても使われる
nodenv
nodenvとは?
nodenvとはNode.jsのバージョンを管理するためのツール。
指定のバーションをインストールしたり、利用するバージョンを切り替えたりできる。
他にはndenvやnodebrewなどがあるが、nodenvは.node-versionファイルを参照して、そこに記載されたバージョンに自動で切り替えてくれるので便利だったためこちらを利用。
実際のインストール方法はこちらの記事を参考にした。
Nodenv環境を用意する - Qiita
nodenvでnode.jsをインストールする
// すでにnodebrewを使っている場合はパスを外す(でないとそちら優先されることがある)
// 今回は8.11.1を使用するためにインストール
nodenv install 8.11.1
nodenv rehash
// ローカル環境で利用するバージョンを指定する
nodenv local 8.11.1
// バージョンの確認
nodenv version
=> 8.11.1
node -v
=> 8.11.1
Yarn
Yarnとは?
Yarnとはパッケージマネジャーの一つ。
概要を理解するために押さえておくべきなのは、package.jsonとyarn.lockの二つ。依存関係とバージョン | Yarn
- package.json: インストールしたパッケージのバージョンなどが管理されている
- yarn.lock: 直接編集することはないが、パッケージ自体が依存しているパッケージ(サブパッケージ)も含めて管理されている
基本的なコマンド
まずプロジェクトの新規作成をする。
yarn init
主に使うのはyarn add
コマンド。yarn add | Yarn
Yarnはパッケージへの依存関係をグループ化して管理する。
主に利用されるのは、dependencies
とdevDependencies
の二つ。
詳しくはこちらのページを参照されたし。
yarn add <pachage...>
でdependencies
としてインストールされる。
これれは通常の依存関係か、もしくはコードの実行時に必要なもの(例えば React または ImmutableJS など)です。
yarn add <pachage...> [--dev/-D]
でdevDependencies
としてインストールされる。
これらは開発用の依存関係です。開発ワークフローのどこかで必要で、コードの実行時には必要のない依存関係です(例:Babel もしくは Flow)。
versionの指定方法
package.jsonに記載されるパッケージのバージョン。
Versions of dependencies | Yarn
Caret Ranges (^
) はゼロ以外の最初の桁の数字を上げない限りのバージョンアップを許す。
^2.3.1
=> >=2.3.1 < 3.0.0
^0.5.1
=> >=0.5.1 < 0.6.0
^0.0.7
=> >=0.0.7 < 0.0.8
webpack
webpackとは?
JavaScriptやHTML, CSSはブラウザ上で描画されるために処理、実行される。
この辺りの仕組みの概要を知りたければこちらの本の前半の章を読むと分かりやすい。
Webフロントエンド ハイパフォーマンス チューニング | 久保田 光則 | 工学 | Kindleストア | Amazon
そのためには、サーバにあるJavaScriptなどのファイルをロードする必要がある。
しかし、これらのファイルは通常複数あり、全てファイルを読み込み、処理をするとユーザは延々と待ち続けることになる。そのために、それらのファイル(モジュール)をまとめて一つにし、ブラウザ(JavaScriptエンジンなど)が実行しやすいようにビルドしたファイルを作る必要がある。それを実現するのがモジュールバンドラー。
そしてwebpackはアクセスしたページで利用されているファイルを読み込み一つのファイルにすることができる。
しかし、昨今ではフロントエンドの担う役割は年々増大しており、それに伴ってフロントエンドの占めるコードの割合も増大しているので、それを1つのファイルに落とし込むとなると、ファイルサイズはかなりのものになります。(中略) そのファイルを初回アクセス時にユーザーに読み込ませるとなると、無関係のコードも含まれる1つのファイルの読み込みを、ユーザーは延々と待たされることになります。(中略) 理想はアクセスしたページに依存関係のあるコードだけが含まれるファイルが読み込まれ、初期ローディングが必要最小限に抑えられることでしょう。これらの問題を解決するために既存のモジュール・バンドラーを拡張することも試みられたそうですが、目的を果たすことができずwebpackを開発するに至ったことが記されています。
これから始めるwebpack - webpackの基礎知識 | CodeGrid
webpackの設定をする
主にこの記事を参考にした。サルでもわかるwebpack 4.5入門 - 古い情報に騙されずに学ぼう - ICS MEDIA
webpackをインストールする
yarn add -D webpack webpack-cli
webpack.config.jsを設定する
複数のJavaScriptファイルを集約したJavaScriptファイルをエントリーポイントという。
module.exports = {
// エントリーポイント
entry: `./src/index.js`,
// ビルドされた実行ファイルの出力設定
output: {
// 出力ファイルのディレクトリ名
path: `${__dirname}/dist`,
// 出力ファイル名
filename: 'bundle.js'
},
};
webpackでバンドルしてみる
JavaScriptのバンドルファイルを作る
// ./src/index.js
import { hello } from './sub';
hello();
// ./src/sub.js
export function hello() {
alert('Hello World');
}
実際にビルドされたファイル。
設定でモードを選ぶことでソースマップ(どこのソースコードから作られたか)などの情報も付与して出力することができる。
デフォルトだと本番用に圧縮された状態で出力される。
実際にビルドしてみる。
> yarn run webpack
Hash: 302f700e2ea67728f905
Version: webpack 4.7.0
Time: 259ms
Built at: 2018-05-05 17:19:47
Asset Size Chunks Chunk Names
bundle.js 587 bytes 0 [emitted] main
Entrypoint main = bundle.js
[0] ./src/index.js + 1 modules 91 bytes {0} [built]
| ./src/index.js 40 bytes [built]
| ./src/sub.js 51 bytes [built]
./dist/bundle.js
に出力される。
// ./dist/bundle.js
!function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r,t){"use strict";t.r(r),alert("Hello World")}]);
Babel
Babelとは?
ECMAScriptのトランスパイラ。flowTypeやJSX、ECMAScript2015 (ES6) などのソースコードをサポートしていないブラウザが存在するので、実行できるように取り除いたり、それ以前の書き方に変換したりすることができる。
こちらのページで試すことができる。
そして、これらが変換された後にwebpackがバンドルする。
flowtype付きのES2015の記法を使って書いたもの。
// @flow
const inc = (x: number):number => { x + 1 };
const newArray: Array<numebr> = [...[1, 2, 3], 4, 5];
それらがES2016以前の書き方に変換される。
"use strict";
var inc = function inc(x) {
x + 1;
};
var newArray = [1, 2, 3].concat([4, 5]);
Babelを使う
主にこの記事を参考にした。最新版で学ぶwebpack 4入門 - BabelでES2017環境の構築(React, Vue, Three.js, jQueryのサンプル付き) - ICS MEDIA
インストールする
yarn add -D babel-core babel-loader babel-preset-env babel-preset-react
webpack.config.jsを設定する
// webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
use: [
{
// Babelを利用する
loader: 'babel-loader',
options: {
presets: [
['env', { 'modules': false }]
]
}
}
]
}
]
}
};
React
reactをインストールする
yarn add react react-dom
webpackの設定をする
// webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
// Babel のオプションを指定する
options: {
presets: [
['env', { 'modules': false }],
// React の JSX を解釈
'react'
]
}
}
],
// node_modules は除外する
exclude: /node_modules/,
}
]
}
};
babelの設定をする
// .babelrc
{
"presets": ["react"]
}
webpack-dev-serverを使う
まずインストールする。
yarn add -D webpack-dev-server
webpackで起動させるサーバの設定を行う。
// webpack.config.js
module.exports = {
entry: `./src/index.js`,
...
devServer: {
port: 3000,
contentBase: 'dist'
},
module: {
...
}
};
yarn run webpack-dev-server
でhttp://localhost:3000/
にアクセスすると表示されるようになる。
実際に書いてみる
// ./src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import HelloMessage from './sub';
class App extends React.Component {
render() {
return (
<div>
<h1>Hello React!</h1>
<HelloMessage
message="with Babel & webpack"
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('react-root'));
// ./src/sub.js
const HelloMessage = (props) => {
<h3>{props.message}</h3>
};
export default HelloMessage;
// ./dist/index.html
<!doctype html>
<html lang="en">
<body>
<div id="react-root"></div>
<script src="/bundle.js"></script>
</body>
</html>
表示される!
eslint
eslintとは、JavaScritpやJSXの構文チェッカーのこと。
この記事などを見て設定をした。
ESLint 最初の一歩 - Qiita
インストールする。
yarn add -D eslint eslint-plugin-react
.eslintrcファイルでチェック時のルールを設定することができる。
// .eslintrc
{
"parser": "babel-eslint",
"plugins": [
"flowtype",
"react"
],
"settings": {
"flowtype": {
"onlyFilesWithFlowAnnotation": true
}
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"env": {
"browser": true,
"node": true
},
"rules": {
"quotes": [2, "single"],
"strict": [2, "never"],
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"react/react-in-jsx-scope": 2
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:flowtype/recommended"
]
}
flow
インストールと実行
JavaScritpを型定義するためのもの。こちらのサイトに従ってインストールできる。Installation | Flow
yarn add -D flow-bin
yarn run flow init
yarn run flow
基本設定
.flowconfig
でバージョン指定や、チェック対象のファイルを指定できる。
// node_module以下はチェック対象外にする
[ignore]
.*/node_modules/.*
トランスパイル時に型定義されたコードを取り除く
balel-preset-reactにflowの型定義を取り除くプラグインが含まれている。
babelrcの設定をする。
// .babelrc
{
"presets": ["react"],
}
eslintに型定義されたコードを通す
この記事を参考にした。flowの始め方 - Qiita
eslintと連携するにはbabel-eslintとeslint-plugin-flowtypeをインストールする必要がある。
そうでないとeslintで引っかかる。
yarn add -D eslint-plugin-flowtype babel-eslint
.eslintrc.jsに以下を追加する。
//.eslintrc.js
{
parser: 'babel-eslint',
extends: ['plugin:flowtype/recommended'],
plugins: ['flowtype'],
settings: {
flowtype: {
onlyFilesWithFlowAnnotation: true,
},
},
...
}
flowを使って型定義をする。
// @flow
import React from 'react';
type Props = {
message: string
};
const HelloMessage = (props: Props) => {
return <h3>{props.message}</h3>;
};
export default HelloMessage;
参考
- Nodenv環境を用意する - Qiita
- サルでもわかるwebpack 4.5入門 - 古い情報に騙されずに学ぼう - ICS MEDIA
- はじめてのWebpack - Qiita
- webpack 4 入門 - Qiita
- これから始めるwebpack - webpackの基礎知識 | CodeGrid
- 最新版で学ぶwebpack 4入門 - BabelでES2017環境の構築(React, Vue, Three.js, jQueryのサンプル付き) - ICS MEDIA
- Yarnを利用して、Reactをwebpack と babel-loaderでビルドする方法 - Qiita
- ESLint 最初の一歩 - Qiita
- flowの始め方 - Qiita