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

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生活

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
ユーザーは見つかりませんでした