iT邦幫忙

2022 iThome 鐵人賽

DAY 22
1
Modern Web

前端技能樹的十萬個為什麼系列 第 22

Day 22 - 為什麼要用 Create-React-App

  • 分享至 

  • xImage
  •  

前言

到今天之前,已經介紹了各種各樣第三方套件與工具,基本上一個一個都看得懂,都會用,但若真要我從零開始到異世界建置一個 React 專案,我反而會愣住

痾。。。我該怎麼從頭開始?

突然體會到,學了很多從 1 到 100 的技能,但現在要從 0 到 1,好像就一時間不知道該怎麼辦,或者即便知道怎麼開始,過程應該也是相當冗長。

因此,今天我們來看看 Create-React-App 吧!

先想一下

  • Create-React-App 是在什麼樣的時代誕生的?
  • Create-React-App 怎麼解決問題?
  • Create-React-App 的優缺點是什麼?
  • Create-React-App 適合什麼情境?

Create-React-App 是在什麼樣的時代誕生的?

若是要寫一個 React 的 SPA 網頁,我們會仰賴各種第三方 library 來處理各種基本功能,基本上也都能找到對應的 library:

  • Babel:編譯 ES6+ 讓瀏覽器看懂
  • Webpack:打包資源與程式碼
  • eslint:檢查程式碼
  • 其他...

但是每個套件背後都是一個全新的世界,如果每個都要自己設定(尤其是 Webpack),那專案可能要延後很久才開始,同時,讓新手失去耐心的,往往不是寫 code,而是環境建置XD"

尤其,現在各種 React 專案環境的需求大同小異,要能編譯,要能打包,要能檢查 lint,只有商業邏輯的差異比較大,那既然大家都差不多,怎麼沒有一個「模板」可以直接一鍵生成呢?

Create-React-App 怎麼解決問題?

Create React App 是一個由 Facebook 開發維護的 toolchain,React 官網推薦,用來快速建立一個 pre-configured React 專案

Set up a modern web app by running one command.

CRA 並不會處理 backend 邏輯或資料庫;它只會建立一個 front-end build pipeline,以便你配合任何 backend 來使用。也就是說,前端的開發環境、打包設定,Babel、Webpack、Jest,都已經處理好了,你只要認真開發程式就可以了

只有一個 dependency

一個採用 CRA 的專案,package.json 會像這樣,超級簡潔,而關鍵就在 devDependencies 裡面的那個 react-scripts

{
  "name": "tic_tac_toe",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "react-scripts": "^0.9.5"
  },
  "dependencies": {
    "react": "^15.5.4",
    "react-dom": "^15.5.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

即便真的需要調整設定,也可以將專案 eject,便可以直接操作,但注意這是不可逆的

而如果是經過 eject 指令處理過,則會變成這樣,瞬間像是被解壓縮了一樣:

{
  "name": "tic_tac_toe",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "autoprefixer": "6.7.2",
    "babel-core": "6.22.1",
    "babel-eslint": "7.1.1",
    "babel-jest": "18.0.0",
    "babel-loader": "6.2.10",
    "babel-preset-react-app": "^2.2.0",
    "babel-runtime": "^6.20.0",
    "case-sensitive-paths-webpack-plugin": "1.1.4",
    "chalk": "1.1.3",
    "connect-history-api-fallback": "1.3.0",
    "cross-spawn": "4.0.2",
    "css-loader": "0.26.1",
    "detect-port": "1.1.0",
    "dotenv": "2.0.0",
    "eslint": "3.16.1",
    "eslint-config-react-app": "^0.6.2",
    "eslint-loader": "1.6.0",
    "eslint-plugin-flowtype": "2.21.0",
    "eslint-plugin-import": "2.0.1",
    "eslint-plugin-jsx-a11y": "4.0.0",
    "eslint-plugin-react": "6.4.1",
    "extract-text-webpack-plugin": "1.0.1",
    "file-loader": "0.10.0",
    "fs-extra": "0.30.0",
    "html-webpack-plugin": "2.24.0",
    "http-proxy-middleware": "0.17.3",
    "jest": "18.1.0",
    "json-loader": "0.5.4",
    "object-assign": "4.1.1",
    "postcss-loader": "1.2.2",
    "promise": "7.1.1",
    "react-dev-utils": "^0.5.2",
    "style-loader": "0.13.1",
    "url-loader": "0.5.7",
    "webpack": "1.14.0",
    "webpack-dev-server": "1.16.2",
    "webpack-manifest-plugin": "1.1.0",
    "whatwg-fetch": "2.0.2"
  },
  "dependencies": {
    "react": "^15.5.4",
    "react-dom": "^15.5.4"
  },
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --env=jsdom"
  },
  "jest": {
    "collectCoverageFrom": [
      "src/**/*.{js,jsx}"
    ],
    "setupFiles": [
      "<rootDir>/config/polyfills.js"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>[/\\\\](build|docs|node_modules|scripts)[/\\\\]"
    ],
    "testEnvironment": "node",
    "testURL": "http://localhost",
    "transform": {
      "^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest",
      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
      "^(?!.*\\.(js|jsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
    },
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"
    ],
    "moduleNameMapper": {
      "^react-native$": "react-native-web"
    }
  },
  "babel": {
    "presets": [
      "react-app"
    ]
  },
  "eslintConfig": {
    "extends": "react-app"
  }
}

注意其中不只 devDependencies 展開而已,一些像是 babeleslintConfig 的設定,也會被貼進來。

Create-React-App 的優缺點是什麼?

優點

  • 一行 code 就啟動一個 React 專案,只要專注在程式邏輯開發,不需要擔心 Webpack、Babel 或其他 dependencies
  • 僅需要維護一個 dependency(即 react-scripts)
  • 有各種預設模板可以使用

缺點

  • config 較難新增與客製化
  • 初學者容易混淆,以為 react-scripts 就包辦了一切,像黑箱一樣難以看透
  • 如果有用不到的套件,仍然會在裡面佔位子

Create-React-App 適合什麼情境?

CRA 最適合不需要特別設定、追求快速開發的 React 專案,可以快速建立專案,並跳過基礎設定的階段,進入程式邏輯開發。

雖然 CRA 跳過了一些基礎設定,可能會讓新手對於基礎設定變得陌生,但或許這就是一個需要被理解的 tradeoff,起碼要先知道

哦!CRA 其實幫我處理掉 Babel、Webpack 的部分

在這個認知的前提下,可以先專注在程式邏輯開發,但務必要在熟悉了之後,再回頭來好好搞懂,CRA 究竟做了哪些事,才會對自己的專案完全掌握。

結語

心智圖放大版

其實我認識 CRA 的過程相當奇妙曲折,最一開始其實不知道有這樣方便的工具,進公司接手既有的 React 專案時,發現怎麼 A 專案可以輕易改 Webpack 的設定,B 專案卻很麻煩,我都是寫 React 啊!查了一下才發現原來 B 專案是用 CRA 建置的,這才恍然大悟!

雖然我都是接手別人已經建好的專案,不過看到上面提到,eject 前、後的 package.json 差異,著實是驚呆了!原來 CRA 做了那麼多事情啊!

參考資料

Create React App
為何不用 create-react-app: 如何設置自己的 reactjs 樣板


上一篇
Day 21 - 為什麼要用 npm
下一篇
Day 23 - 為什麼要用 Styled-components
系列文
前端技能樹的十萬個為什麼30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言