本文差點難產而死。由於總結的過程當中,屢次懷疑本文是對官方文檔的直接翻譯和簡單諾列;同時官方文檔很全面,全範圍的介紹無疑加深了寫做的心智負擔。但在最終的梳理中,發現走出了一條不同凡響的路,因而堅持分享出來。javascript
但願本文除了能帶領咱們再次瞭解 Create React App(後文簡稱 CRA) 外,還能提供一種不一樣的知識組織結構和技術視角,加深咱們對整個 React 技術生態的理解。css
本文多是多篇博客的綜合體,整理和寫做時間 15h+,仔細閱讀時間 30min+,請慢用。
本文面向的讀者是:html
其次,本文在對官方文檔進行必定的從新編排下,加上了以下創新點以完善總體的閱讀學習體驗:前端
最終,本文不涉及源碼的解讀,想要閱讀源碼的同窗能夠移步官方源碼倉庫,總體設計思路並非很難,具體實現原理能夠細細品嚼;且本文對與 CRA 不直接相關的技術點會略略而過,歡迎從點到面主動學習更多。如下是官方源碼倉庫以及官方文檔地址:java
常見的初始化 React App 的方式有:node
下面咱們分別進行介紹與實戰練習。react
React 自己專一於構建用戶界面,並不依賴於某個構建工具,所以咱們能夠用傳統的方式引入 React 並書寫第一個「Hello World!」 App。這種方式是快速嘗試 React 的好方法,但並不適用於正式開發。webpack
如下 HTML 代碼段是一種實現方式,使用了可選的 Babel 編譯和 JSX 語法,基於非構建工具的更多初始化頁面的方法(如不使用 JSX 等)能夠自行探索。git
<html> <head> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <!-- 不須要用於生產環境 --> </head> <body> <div id="root"></div> <script type="text/babel"> ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') ) </script> </body> </html>
構建工具備不少種,目前最爲主流的構建工具當屬 Webpack。如何使用 Webpack 逐步構建 React App?github
果不其然,爲了證實 CRA 的便捷性而引出的本節 Webpack 實戰,耗費了一小時多的時間進行了親自踩坑,搜索了較多的博文都因爲發佈時間性而不能和最新的版本進行融合,最終根據 Github 中 react-webpack-babel 庫的 package.json 文件裏的相關信息才獲得實現。
# 建立一個項目並進入該項目 $ mkdir react-webpack-steper & cd react-webpack-steper # 使用默認選項直接生成一個初始化的 package.json $ npm init -y # 安裝 React 基礎包 $ sudo npm install --save react react-dom # 安裝 Webpack 相關工具 - 打包、本地啓動支持、本地異步請求模擬以及熱更新等 $ sudo npm install --save webpack webpack-cli webpack-dev-server # 安裝 Babel 相關工具 - 提供 ES6+ 新功能支持 $ sudo npm install --save-dev @babel/cli @babel-core @babel/preset-env @babel/preset-react $ sudo npm install --save-dev babel-loader babel-plugin-module-resolver html-webpack-plugin # 新建打包、編譯配置文件並準備編寫 $ touch webpack.config.js $ touch .babelrc # 新建 React 文件 $ mkdir src $ touch src/index.js $ touch src/index.html
其中,webpack.config.js 源碼以下:
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { entry: path.resolve(__dirname, './src/index.js'), module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }, ] }, resolve: { extensions: ['*', '.js', '.jsx'] }, output: { path: path.resolve(__dirname, './build'), filename: 'bundle.js', publicPath: '/' }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, './src/index.html') }) ] }
.babelrc 源碼以下:
{ "presets": ["@babel/preset-env", "@babel/preset-react"], "plugins": [ ["module-resolver", { "root": ["./src"] }] ] }
src/index.html 源碼以下:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Hello World!</title> </head> <body> <div id="root">Loading...</div> </body> </html>
src/index.js 源碼以下:
import React from 'react' import ReactDOM from 'react-dom' ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') )
此時,一個基於 Webpack 手動搭建的簡易型「Hello World」App 開發完成,能夠經過以下命令本地運行。
$ webpack-dev-server --mode development --open --hot
更多自定義內容如添加 devServer 支持、添加多頁應用支持...等各類各樣新技術棧的支持,也能夠引伸實戰。
可見,不使用構建工具編寫不切實際,使用構建工具手動搭建 React App 又很繁瑣。所以咱們須要一個能初始化一個可直接運行項目的工具,並提供各類簡易的插件,Create React App 應運而生。
CRA 適用於中小型 React 項目。
CRA 將具備構建現代單頁 React 應用所需的一切:
Create React App 很是適合:
若是咱們想在沒有數百個傳遞構建工具依賴的狀況下嘗試 React,請考慮使用單個 HTML 文件構建或使用在線沙箱平臺構建。
一些支持的瀏覽器規則以下:
這裏的重點是 BrowsersList,一個「在不一樣的前端工具之間共用目標瀏覽器和 node 版本的配置工具」。簡而言之,就是 Babel 等轉移工具經過咱們設置的 BrowsersList 中想要支持的瀏覽器版原本決定哪些語法須要被編譯。
一些支持的 ES 標準規則以下:
該項目支持最新 JavaScript 標準的超集。 除ES6語法功能外,它還支持:
Create React App 有兩個核心庫,以下:
到這裏,咱們終於須要經過命令行來安裝和使用 CRA,來構建咱們的第三個「Hello World」App。
爲保證每個新項目都能使用到 CRA 最新最全的功能,請確保 CRA 爲最新版本。
# 再已安裝 CRA 的狀況下,能夠先卸載 CRA $ npm uninstall -g create-react-app # 正式安裝 CRA $ npm install -g create-react-app
根據咱們的 npm 版本,選擇相應命令來安裝最新版的 CRA 並初始化第一個項目。同時檢查本身的 node 版本,須要在本地開發計算機上安裝 Node 8.16.0 或 Node 10.16.0 或更高版本(但服務器上不須要)。 咱們可使用nvm(macOS / Linux)或 nvm-windows 在不一樣項目之間切換Node版本。
# 查看本身的 npm 版本 $ npm --version # 第一種新建項目方式——npm 5.2+ 時,如下命令會安裝最新版 CRA $ npx create-react-app my-app # 第一種新建項目方式——npm 版本小於等於 5.1 時 $ create-react-app my-app # 第二種新建項目方式 # npm 6+ 開始支持 npm init <initializer> $ npm init react-app my-app # 第三種新建項目方式 $ yarn create react-app my-app
經過命令行的構建,咱們初始化了第一個 CRA 項目,其中幫咱們生成的項目目錄結構以下(只有 src 下的文件纔會被 Webpack 處理,只有 public 下的文件才能被 public/index.html 使用):
my-app ├── .git # 隱藏文件夾,會初始化第一個 Commit 記錄 ├── README.md ├── node_modules ├── package.json # 依賴配置文件 ├── .gitignore ├── [floder_name] # 根目錄下能夠創建其餘文件夾,但不會被用在生產環境中 ├── public # 只有 public 下的文件才能被 public/index.html 使用 │ ├── favicon.ico │ ├── index.html # public/index.html 頁面模板 │ └── manifest.json └── src # 只有 src 下的文件纔會被 Webpack 處理 ├── App.css ├── App.js ├── App.test.js ├── [floder_name] # 能夠創建其餘文件夾,以被 Webpack 成功導入 ├── index.css ├── index.js # JavaScript 打包入口文件 ├── logo.svg └── serviceWorker.js
關於 package.json、index.js 和 public/index.html 文件夾,咱們經過「實戰 2」已經有所瞭解。前者是 JavaScript 打包入口文件,一般連接整個業務代碼;後者是頁面模板,是打包後整個靜態頁面的總入口。
這裏對如下兩個文件的出現進行簡要的意義歸納。
_
CRA 默認提供了運行、測試、打包、部署以及彈出項目的命令。其中的一些貼士:
# ---- 運行 ---- $ npm start $ open http://localhost:3000 # ---- 測試 ---- $ npm test # ---- 打包 ---- $ npm run builds # ---- 彈出配置 ---- $ npm run eject
根據官方文檔的思路,咱們還能從更多角度拓展 CRA 的使用邊界,下面進行概要介紹。
這裏沒法深刻展開,每個點均可以是一個新的實戰,當咱們須要某個功能時即可以查閱相關文檔來主動探索。其中「分析打包文件」的解讀見「實戰 4」。
# 安裝文件分析工具 source-map-explorer $ sudo npm install --save source-map-explorer # 打包項目 $ npm run build # 將以下命令放入 package.json 中並生成快捷方式 npm run analyze # $ source-map-explorer 'build/static/js/*.js' # 注意此命令直接在命令行輸入會提示找不到相關命令 $ npm run analyze
對於一個剛被 CRA 生成的 React App 來講,分析的結果以下,包大總計 129.38k。
回到剛纔「實戰 2」創建的 react-webpack-steper 項目中,當咱們已經編寫了一部分業務時,可否直接在當前項目中無痛引入 CRA?
解決思路即是:在大多數狀況下,更改 package.json 中的 react-scripts 版本並刪除沒必要要文依賴配置,接着在此文件夾中運行 npm install 就足夠了,但最好參考更改日誌以瞭解潛在的重大更改。CRA 致力於將重大更改保持在最低限度,以即可以輕鬆升級 React 腳本。
# 卸載 CRA 自己已經提供的依賴 $ sudo npm uninstall --save webpack webpack-cli webpack-dev-server $ sudo npm uninstall --save-dev @babel/cli @babel-core @babel/preset-env @babel/preset-react $ sudo npm uninstall --save-dev babel-loader babel-plugin-module-resolver html-webpack-plugin # 刪除 CRA 不須要使用的文件 $ rm webpack.config.js .babelrc # 刪除 node_modules $ rm -rf node_modules # 手動安裝 React Script $ sudo npm install --save react-scripts@latest # 因爲 CRA 默認規則,將 src/index.html 移至 public/index.html $ mkdir public $ mv src/index.html public # 在 package.json 中添加 React Script 啓動命令 $ vim package.json
package.json 中添加/覆蓋以下指令。
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject",
再次執行便可。因爲每一個人的具體配置不必定一致,可根據自身所遇問題進行搜索。升級原理相似。
# 當沒有 BrowsersList 時,CRA 會進行詢問並幫助咱們生成 $ npm start
CRA 官方並不推薦使用 npm run eject 彈出配置,這會增長更多的 Webpack 維護工做。對於實在想改的 Webpack 配置來講,咱們可使用 React App Rewired 庫進行配置注入,這裏來作個小例子。
此工具能夠在不 'eject' 也不建立額外 react-scripts 的狀況下修改 create-react-app 內置的 webpack 配置,而後你將擁有 create-react-app 的一切特性,且能夠根據你的須要去配置 webpack 的 plugins, loaders 等。
繼續使用 react-webpack-steper 項目,咱們的簡易目標是增長 devServer 本地代理。
第一步:安裝依賴並進行基礎配置
# 安裝依賴 $ sudo npm install --save-dev react-app-rewired customize-cra # 根目錄創建 config-overrides.js $ touch config-overrides.js # 修改 package.json $ vim package.json # 運行項目 $ npm start
其中,config-overrides.js 的初始代碼爲:
/* config-overrides.js */ module.exports = function override(config, env) { //do stuff with the webpack config... return config; }
package.json 的修改思路爲:
/* package.json */ "scripts": { - "start": "react-scripts start", + "start": "react-app-rewired start", - "build": "react-scripts build", + "build": "react-app-rewired build", - "test": "react-scripts test --env=jsdom", + "test": "react-app-rewired test --env=jsdom", "eject": "react-scripts eject" }
第二步:編寫配置,進行代理
# 新增配置文件 $ mkdir config $ touch config/proxy.js # 修改 config-overrides.js $ vim config-overrides.js
其中,config/proxy.js 源碼是:
module.exports = { '/api/**': { target: 'http://110.114.120.120:8080', secure: false, changeOrigin: false, }, }
config-overrides.js 修改成:
const { overrideDevServer } = require('customize-cra') const proxy = require('./config/proxy') module.exports = { devServer: overrideDevServer((config) => { config.proxy = proxy return config }), }
此時,本地的全部 api 開頭的接口請求都會被轉發到 http://110.114.120.120:8080 的模擬後端 IP 上。
截止目前(2020-01-10),CRA 的最新版本是 v3.3.0,咱們能夠從 Github 的 MileStone 中看到將來可能會改善的功能,其中整理並以下所述。
讓咱們一塊兒持續關注。
回顧文章,咱們從初始化 React App 的多種方式,引出 CRA 的必要性再對其進行較爲充分的解釋,最後配上 6 個角度來從一些角度對 CRA 的使用方式進行了實戰,最後迴歸到 CRA 的版本展望之中。
感謝你的閱讀,若是你有什麼更多的疑惑,CRA 的官方文檔 + 開源倉庫必定會知足你的一切。
最後,一塊兒拜讀一下 CRA 和 Redux 做者、React 的核心貢獻者 Dan Abramov 發佈的這篇「個人十年回顧」文章。
如今咱們能夠開始正式深刻地學習 React 技術棧了。