JavaScript
react.js
reactjs
React
create-react-app

create-react-app が裏で何をやっているか理解する

More than 1 year has passed since last update.


はじめに

create-react-app 便利ですね!

僕は reactcreate-react-app から入ったクチなので先輩方から「 react は昔は環境構築大変だった」とよく聞きますがいまいちピンと来ていません。

というわけで create-react-app が裏で何をやっているかまとめます。


対象読者



  • create-react-app 使ってはいるけど、何やってるかあんまり分かってない人(僕)


この記事でやること



  1. create-react-app でアプリ作成


  2. create-react-app でアプリ作成し、 npm run ejectcreate-react-app コマンドでパッケージされた状態を外す

  3. 1と2を比較

以下、

1 の create-react-app のオリジナルの状態は create-react-app-org ディレクトリ、

2 の npm run ejectcreate-react-app-eject ディレクトリ、

でやることにします。


1. create-react-app を普通に実施


環境構築

node はインストールされてる前提。

$ node -v 

v8.11.1
$ npm -v
5.6.0
$ npm install -g create-react-app
$ mkdir create-react-app-org
$ cd create-react-app-org
$ create-react-app hello-world
$ cd hello-world


実行

以下のどちらか。

development 環境

$ npm start

production build 環境

$ cd src

$ npm run build
$ cd ../build
$ npm install -g http-server
$ hs

ブラウザでアクセス http://127.0.0.1:8080


SS 11.PNG


はい、デフォルトのアプリ起動しました。

ほんと、簡単で素晴らしいですね。

ここで、 create-react-app hello-world 時のログ、

$ create-react-app hello-world

Success! Created hello-world at /path/to/create-react-app-org/hello-world
Inside that directory, you can run several commands:

npm start
Starts the development server.

npm run build
Bundles the app into static files for production.

npm test
Starts the test runner.

npm run eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

cd hello-world
npm start

Happy hacking!
$

が気になります。


2. create-react-appnpm run eject


環境構築

$ mkdir create-react-app-eject

$ cd create-react-app-eject
$ create-react-app hello-world
$ cd hello-world


npm run eject

$ npm run eject

> hello-world@0.1.0 eject /path/to/create-react-app-eject/hello-world
> react-scripts eject

? Are you sure you want to eject? This action is permanent. Yes
Ejecting...

Copying files into /path/to/create-react-app-eject/hello-world
Adding /config/env.js to the project
Adding /config/paths.js to the project
Adding /config/polyfills.js to the project
Adding /config/webpack.config.dev.js to the project
Adding /config/webpack.config.prod.js to the project
Adding /config/webpackDevServer.config.js to the project
Adding /config/jest/cssTransform.js to the project
Adding /config/jest/fileTransform.js to the project
Adding /scripts/build.js to the project
Adding /scripts/start.js to the project
Adding /scripts/test.js to the project

Updating the dependencies
Removing react-scripts from dependencies
Adding autoprefixer to dependencies
Adding babel-core to dependencies
Adding babel-eslint to dependencies
Adding babel-jest to dependencies
Adding babel-loader to dependencies
Adding babel-preset-react-app to dependencies
Adding babel-runtime to dependencies
Adding case-sensitive-paths-webpack-plugin to dependencies
Adding chalk to dependencies
Adding css-loader to dependencies
Adding dotenv to dependencies
Adding dotenv-expand to dependencies
Adding eslint to dependencies
Adding eslint-config-react-app to dependencies
Adding eslint-loader to dependencies
Adding eslint-plugin-flowtype to dependencies
Adding eslint-plugin-import to dependencies
Adding eslint-plugin-jsx-a11y to dependencies
Adding eslint-plugin-react to dependencies
Adding extract-text-webpack-plugin to dependencies
Adding file-loader to dependencies
Adding fs-extra to dependencies
Adding html-webpack-plugin to dependencies
Adding jest to dependencies
Adding object-assign to dependencies
Adding postcss-flexbugs-fixes to dependencies
Adding postcss-loader to dependencies
Adding promise to dependencies
Adding raf to dependencies
Adding react-dev-utils to dependencies
Adding resolve to dependencies
Adding style-loader to dependencies
Adding sw-precache-webpack-plugin to dependencies
Adding url-loader to dependencies
Adding webpack to dependencies
Adding webpack-dev-server to dependencies
Adding webpack-manifest-plugin to dependencies
Adding whatwg-fetch to dependencies

Updating the scripts
Replacing "react-scripts start" with "node scripts/start.js"
Replacing "react-scripts build" with "node scripts/build.js"
Replacing "react-scripts test" with "node scripts/test.js"

Configuring package.json
Adding Jest configuration
Adding Babel preset
Adding ESLint configuration

Running npm install...
added 1 package and updated 2 packages in 8.329s
Ejected successfully!

Please consider sharing why you ejected in this survey:
http://goo.gl/forms/Bi6CZjk1EqsdelXk1

$


何が起きたのか?

create-react-app コマンドで作られた環境は react-scripts でまるっとまとめられていたのですが、それを解放して、必要なモジュールを一つ一つ手でインストールしたのと同じ状態になりました。


npm run eject 後の状態でも

development 環境

$ npm start

production build 環境

$ cd src

$ npm run build
$ cd ../build
$ npm install -g http-server
$ hs

ブラウザでアクセス http://127.0.0.1:8080

create-react-app と同様、どちらでもアプリ実行可能です。


3. 比較

npm run eject 前後の比較をします。


package.json


create-react-app 素の状態

/path/to/create-react-app-org/hello-world$ cat package.json 

{

"name": "hello-world",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-scripts": "1.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}


npm run eject

/path/to/create-react-app-eject/hello-world$ cat package.json 

{

"name": "hello-world",
"version": "0.1.0",
"private": true,
"dependencies": {
"autoprefixer": "7.1.6",
"babel-core": "6.26.0",
"babel-eslint": "7.2.3",
"babel-jest": "20.0.3",
"babel-loader": "7.1.2",
"babel-preset-react-app": "^3.1.1",
"babel-runtime": "6.26.0",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "1.1.3",
"css-loader": "0.28.7",
"dotenv": "4.0.0",
"dotenv-expand": "4.2.0",
"eslint": "4.10.0",
"eslint-config-react-app": "^2.1.0",
"eslint-loader": "1.9.0",
"eslint-plugin-flowtype": "2.39.1",
"eslint-plugin-import": "2.8.0",
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "7.4.0",
"extract-text-webpack-plugin": "3.0.2",
"file-loader": "1.1.5",
"fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0",
"jest": "20.0.4",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "2.0.8",
"promise": "8.0.1",
"raf": "3.4.0",
"react": "^16.3.2",
"react-dev-utils": "^5.0.1",
"react-dom": "^16.3.2",
"resolve": "1.6.0",
"style-loader": "0.19.0",
"sw-precache-webpack-plugin": "0.11.4",
"url-loader": "0.6.2",
"webpack": "3.8.1",
"webpack-dev-server": "2.9.4",
"webpack-manifest-plugin": "1.3.2",
"whatwg-fetch": "2.0.3"
},
//略

create-react-app 素の状態では、dependencies が react, react-dom, react-scripts の僅か3パッケージだったのに対し、 npm run eject するとパッケージ数が途端に増えました。


ディレクトリ構成


create-react-app 素の状態

/path/to/create-react-app-org/hello-world$ tree -I 'node_modules'

.
├── README.md
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js

2 directories, 13 files
$


npm run eject

/path/to/create-react-app-eject/hello-world$ tree -I 'node_modules'

.
├── README.md
├── config
│   ├── env.js
│   ├── jest
│   │   ├── cssTransform.js
│   │   └── fileTransform.js
│   ├── paths.js
│   ├── polyfills.js
│   ├── webpack.config.dev.js
│   ├── webpack.config.prod.js
│   └── webpackDevServer.config.js
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── scripts
│   ├── build.js
│   ├── start.js
│   └── test.js
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js

5 directories, 24 files
$

create-react-app 素の状態では、ほぼソースファイルのみだったのに対し、 npm run eject すると隠れていた config ファイルが現れます。


まとめ

本来大量のパッケージと設定ファイルをしこしこ用意して react 環境を作らねばならなかったところ、

create-react-app コマンドは一発でその環境を用意し、良い感じに隠蔽し、ソースファイルを見やすく、開発しやすくするツールでした。

#もちろん、細かく手を入れたければ npm run eject してカスタマイズ。もしくはイチから環境構築。


参考

Facebook公式のcreate-react-appコマンドを使ってReact.jsアプリを爆速で作成する

Facebook 公式ツール Create React App を使って React 開発の初歩を学ぶチュートリアル

2018 年 React と Redux のエコシステム総まとめ

ゼロから始めるJavaScript生活