深入淺出 Create React App

本文差點(diǎn)難產(chǎn)而死。因?yàn)榭偨Y(jié)的過程中文黎,多次懷疑本文是對(duì)官方文檔的直接翻譯和簡(jiǎn)單羅列惹苗;同時(shí)官方文檔很全面,全范圍的介紹無疑加深了寫作的心智負(fù)擔(dān)耸峭。但在最終的梳理中桩蓉,發(fā)現(xiàn)走出了一條與眾不同的路,于是堅(jiān)持分享出來劳闹。

希望本文除了能帶領(lǐng)我們?cè)俅瘟私?Create React App(后文簡(jiǎn)稱 CRA) 外院究,還能提供一種不同的知識(shí)組織結(jié)構(gòu)和技術(shù)視角,加深我們對(duì)整個(gè) React 技術(shù)生態(tài)的理解本涕。

本文可能是多篇博客的綜合體业汰,整理和寫作時(shí)間 15h+,仔細(xì)閱讀時(shí)間 30min+菩颖,請(qǐng)慢用样漆。

本文面向的讀者是:

  • 前端開發(fā)初學(xué)者或 React 初學(xué)者;
  • 使用過 CRA 搭建 React 項(xiàng)目但想拓展相關(guān)知識(shí)面的人晦闰;
  • 希望通過一篇文章快速復(fù)習(xí) CRA 的人放祟;
  • 英文初學(xué)者,想要通過一篇中文技術(shù)文章來讓自己接下來讀英文文檔不再困難的人呻右;
  • 以及就想點(diǎn)進(jìn)來支持一下的人舞竿。

其次,本文在對(duì)官方文檔進(jìn)行一定的重新編排下窿冯,加上了如下創(chuàng)新點(diǎn)以完善整體的閱讀學(xué)習(xí)體驗(yàn):

  • 添加了實(shí)戰(zhàn) 1:使用單個(gè) HTML 文件構(gòu)建 React App骗奖;
  • 添加了實(shí)戰(zhàn) 2:使用 Webpack 手動(dòng)構(gòu)建 React App;
  • 添加了實(shí)戰(zhàn) 3:使用 CRA 一站式構(gòu)建 React App;
  • 添加了實(shí)戰(zhàn) 4:使用 Source Map Explorer 分析打包文件执桌;
  • 添加了實(shí)戰(zhàn) 5:在已有的 React 項(xiàng)目中引入/升級(jí) CRA鄙皇;
  • 添加了實(shí)戰(zhàn) 6:使用 React App Rewired 注入新配置;
  • 添加了:對(duì) CRA 未來版本的簡(jiǎn)單展望仰挣;
  • 添加了:一個(gè) Dan 十年回顧文章的導(dǎo)讀伴逸。

最終,本文不涉及源碼的解讀膘壶,想要閱讀源碼的同學(xué)可以移步官方源碼倉庫错蝴,整體設(shè)計(jì)思路并不是很難,具體實(shí)現(xiàn)原理可以細(xì)細(xì)品嚼颓芭;且本文對(duì)與 CRA 不直接相關(guān)的技術(shù)點(diǎn)會(huì)略略而過顷锰,歡迎從點(diǎn)到面主動(dòng)學(xué)習(xí)更多。以下是官方源碼倉庫以及官方文檔地址:

初始化 React App 的多種方式

常見的初始化 React App 的方式有:

  • 不使用構(gòu)建工具構(gòu)建 React App亡问;
  • 使用 Webpack 手動(dòng)構(gòu)建 React App官紫;
  • 使用 Create React App 一站式構(gòu)建 React App;
  • 在在線沙箱平臺(tái)直接構(gòu)建 React App(一般用于 Demo 預(yù)演州藕,本文不涉及)束世。

下面我們分別進(jìn)行介紹與實(shí)戰(zhàn)練習(xí)。

實(shí)戰(zhàn) 1:使用單個(gè) HTML 文件構(gòu)建 React App

React 本身專注于構(gòu)建用戶界面床玻,并不依賴于某個(gè)構(gòu)建工具毁涉,因此我們可以用傳統(tǒng)的方式引入 React 并書寫第一個(gè)“Hello World!” App。這種方式是快速嘗試 React 的好方法锈死,但并不適用于正式開發(fā)贫堰。

以下 HTML 代碼段是一種實(shí)現(xiàn)方式,使用了可選的 Babel 編譯和 JSX 語法馅精,基于非構(gòu)建工具的更多初始化頁面的方法(如不使用 JSX 等)可以自行探索。

<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> <!-- 不需要用于生產(chǎn)環(huán)境 -->
  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">
      ReactDOM.render(
        <h1>Hello, world!</h1>,
        document.getElementById('root')
      )
    </script>
  </body>
</html>

實(shí)戰(zhàn) 2:使用 Webpack 手動(dòng)構(gòu)建 React App

構(gòu)建工具有很多種粱檀,目前最為主流的構(gòu)建工具當(dāng)屬 Webpack洲敢。如何使用 Webpack 逐步構(gòu)建 React App?

果不其然茄蚯,為了證明 CRA 的便捷性而引出的本節(jié) Webpack 實(shí)戰(zhàn)压彭,耗費(fèi)了一小時(shí)多的時(shí)間進(jìn)行了親自踩坑,搜索了較多的博文都由于發(fā)布時(shí)間性而不能和最新的版本進(jìn)行融合渗常,最終根據(jù) Github 中 react-webpack-babel 庫的 package.json 文件里的相關(guān)信息才得到實(shí)現(xiàn)壮不。

# 創(chuàng)建一個(gè)項(xiàng)目并進(jìn)入該項(xiàng)目
$ mkdir react-webpack-steper & cd react-webpack-steper
# 使用默認(rèn)選項(xiàng)直接生成一個(gè)初始化的 package.json
$ npm init -y
# 安裝 React 基礎(chǔ)包
$ sudo npm install --save react react-dom
# 安裝 Webpack 相關(guān)工具 - 打包、本地啟動(dòng)支持皱碘、本地異步請(qǐng)求模擬以及熱更新等
$ sudo npm install --save webpack webpack-cli webpack-dev-server
# 安裝 Babel 相關(guān)工具 - 提供 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
# 新建打包询一、編譯配置文件并準(zhǔn)備編寫
$ 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')
)

此時(shí),一個(gè)基于 Webpack 手動(dòng)搭建的簡(jiǎn)易型“Hello World”App 開發(fā)完成健蕊,可以通過如下命令本地運(yùn)行菱阵。

$ webpack-dev-server --mode development --open --hot

更多自定義內(nèi)容如添加 devServer 支持、添加多頁應(yīng)用支持...等各種各樣新技術(shù)棧的支持缩功,也可以引申實(shí)戰(zhàn)晴及。

因此,我們需要 CRA

可見嫡锌,不使用構(gòu)建工具編寫不切實(shí)際虑稼,使用構(gòu)建工具手動(dòng)搭建 React App 又很繁瑣。因此我們需要一個(gè)能初始化一個(gè)可直接運(yùn)行項(xiàng)目的工具势木,并提供各種簡(jiǎn)易的插件蛛倦,Create React App 應(yīng)運(yùn)而生。

CRA 適用于中小型 React 項(xiàng)目跟压。

CRA 的設(shè)計(jì)哲學(xué)

  • 一種依賴關(guān)系胰蝠。盡管 CRA 使用了 Webpack,Babel震蒋,ESLint 等各種出色的項(xiàng)目茸塞,但我們只需要 CRA 一種依賴;從 CRA 生成項(xiàng)目的 package.json 中也可以看到并沒有 Webpack查剖、Babel 的痕跡钾虐。
  • 無需配置。我們無需進(jìn)行任何額外配置便可以直接運(yùn)行代碼笋庄,專注業(yè)務(wù)開發(fā)效扫;同時(shí) CRA 還提供了開發(fā)和生產(chǎn)版本的合理配置。
  • 非鎖定配置直砂。只需要運(yùn)行一個(gè)命令菌仁, 所有的配置項(xiàng)和構(gòu)建依賴項(xiàng)都將直接“彈出”到項(xiàng)目中,交由我們來修改静暂。

CRA 包含了什么济丘?

CRA 將具有構(gòu)建現(xiàn)代單頁 React 應(yīng)用所需的一切:

  • React,JSX洽蛀,ES6摹迷,TypeScript 和 Flow 語法支持;
  • ES6+ 標(biāo)準(zhǔn)的支持郊供,例如對(duì)象傳播運(yùn)算符峡碉;
  • CSS 自動(dòng)添加前綴的支持,因此我們不需要 -webkit- 或其他前綴驮审;
  • 快速的交互式單元測(cè)試運(yùn)行程序鲫寄,內(nèi)置對(duì)覆蓋率報(bào)告的支持吉执;
  • 實(shí)時(shí)開發(fā)服務(wù)器,警告常見錯(cuò)誤塔拳;
  • 一個(gè)構(gòu)建腳本鼠证,用于將 JS,CSS 和圖像與哈希和源映射捆綁在一起進(jìn)行生產(chǎn)靠抑;
  • 滿足所有漸進(jìn)式 Web 應(yīng)用程序標(biāo)準(zhǔn)的 ServiceWorkerWeb 應(yīng)用程序清單 支持 (注意:從react-scripts@2.0.0及更高版本開始支持 ServiceWorker)量九;
  • 單一依賴項(xiàng)即可輕松更新上述工具。

CRA 的使用場(chǎng)景

Create React App 非常適合:

  • 在方便且功能豐富的開發(fā)環(huán)境中學(xué)習(xí) React颂碧;
  • 快速啟動(dòng)新的單頁 React 應(yīng)用程序荠列;
  • 快速使用 React 為庫和組件創(chuàng)建示例。

如果我們想在沒有數(shù)百個(gè)傳遞構(gòu)建工具依賴的情況下嘗試 React载城,請(qǐng)考慮使用單個(gè) HTML 文件構(gòu)建或使用在線沙箱平臺(tái)構(gòu)建肌似。

  • 如果需要將 React 代碼與服務(wù)器端模板框架(如 Rails,Django 或 Symfony)集成诉瓦,或者如果不構(gòu)建單頁應(yīng)用川队,請(qǐng)考慮使用更靈活的 nwbNeutrino。特別是對(duì)于 Rails睬澡,可以使用 Rails Webpacker固额。對(duì)于 Symfony,請(qǐng)嘗試 Symfony's Webpack Encore煞聪;
  • 如果需要發(fā)布 React 組件斗躏,nwb 以及 Neutrino 的 react-components preset 也可以這樣做;
  • 如果要使用 React 和 Node.js 進(jìn)行服務(wù)器渲染昔脯,請(qǐng)查看 Next.jsRazzle啄糙。 Create React App 與后端無關(guān),僅生成靜態(tài)HTML / JS / CSS包云稚;
  • 如果網(wǎng)站大部分是靜態(tài)的(例如隧饼,投資組合或博客),請(qǐng)考慮改用 Gatsby静陈。與 Create React App 不同燕雁,它在構(gòu)建時(shí)會(huì)將網(wǎng)站預(yù)先渲染為 HTML;
  • 最后窿给,如果需要更多自定義設(shè)置贵白,請(qǐng)查看 Neutrino 及其 React preset率拒。

CRA 支持的瀏覽器

一些支持的瀏覽器規(guī)則如下:

  • 默認(rèn)情況下崩泡,生成的項(xiàng)目支持所有現(xiàn)代瀏覽器。 對(duì) Internet Explorer 9猬膨、10 和 11 的支持需要 polyfill角撞。 對(duì)于一組支持舊版瀏覽器的 polyfill呛伴,請(qǐng)使用 react-app-polyfill
  • 默認(rèn)情況下谒所,生成的項(xiàng)目在 package.json 文件中包含一個(gè) browserslist 配置热康,以針對(duì)基于全球使用情況(> 0.2%)的廣泛瀏覽器(用于生產(chǎn)構(gòu)建)和用于開發(fā)的現(xiàn)代瀏覽器。 這提供了良好的開發(fā)體驗(yàn)劣领,尤其是在使用異步/等待等語言功能時(shí)姐军,但仍與生產(chǎn)中的許多瀏覽器保持高度兼容性;
  • browserslist 配置控制輸出的 JavaScript尖淘,以使注入的代碼與指定的瀏覽器兼容奕锌。 通過運(yùn)行構(gòu)建腳本來創(chuàng)建生產(chǎn)構(gòu)建時(shí),將使用生產(chǎn)列表村生,而在運(yùn)行啟動(dòng)腳本時(shí)惊暴,將使用開發(fā)列表。 可以使用 https://browserl.ist 查看配置的瀏覽器列表支持的瀏覽器趁桃;
  • 請(qǐng)注意辽话,這不會(huì)自動(dòng)包括 polyfills,仍然需要根據(jù)所支持的瀏覽器來添加語言功能(見上文)卫病;
  • 在編輯 browserslist 配置時(shí)油啤,我們的更改可能不會(huì)立即被獲取。 這是由于 babel-loader 中的一個(gè)未檢測(cè)到 package.json 中更改的問題忽肛。 一種快速的解決方案是刪除 node_modules/.cache 文件夾村砂,然后重試。

這里的重點(diǎn)是 BrowsersList屹逛,一個(gè)“在不同的前端工具之間共用目標(biāo)瀏覽器和 node 版本的配置工具”础废。簡(jiǎn)而言之,就是 Babel 等轉(zhuǎn)移工具通過我們?cè)O(shè)置的 BrowsersList 中想要支持的瀏覽器版本來決定哪些語法需要被編譯罕模。

CRA 支持的 ES 標(biāo)準(zhǔn)

一些支持的 ES 標(biāo)準(zhǔn)規(guī)則如下:

CRA 的兩個(gè)核心庫

Create React App 有兩個(gè)核心庫,如下:

  • create-react-app 是全局命令证杭,用于創(chuàng)建初始化的 React 項(xiàng)目尾序;
  • react-scripts 是所生成的項(xiàng)目中的開發(fā)依賴項(xiàng),包括運(yùn)行項(xiàng)目躯砰、測(cè)試項(xiàng)目每币、打包項(xiàng)目等多種命令。由于 CRA 的一種依賴性原則琢歇,react-scripts 便開放了所有內(nèi)部其它依賴的使用方式兰怠。

實(shí)戰(zhàn) 3:使用 CRA 構(gòu)建 React App

到這里,我們終于需要通過命令行來安裝和使用 CRA李茫,來構(gòu)建我們的第三個(gè)“Hello World”App揭保。

全局安裝 CRA

為保證每一個(gè)新項(xiàng)目都能使用到 CRA 最新最全的功能,請(qǐng)確保 CRA 為最新版本魄宏。

# 再已安裝 CRA 的情況下秸侣,可以先卸載 CRA
$ npm uninstall -g create-react-app
# 正式安裝 CRA
$ npm install -g create-react-app

初始化 CRA 項(xiàng)目

根據(jù)我們的 npm 版本,選擇相應(yīng)命令來安裝最新版的 CRA 并初始化第一個(gè)項(xiàng)目宠互。同時(shí)檢查自己的 node 版本味榛,需要在本地開發(fā)計(jì)算機(jī)上安裝 Node 8.16.0 或 Node 10.16.0 或更高版本(但服務(wù)器上不需要)。 我們可以使用nvm(macOS / Linux)或 nvm-windows 在不同項(xiàng)目之間切換Node版本予跌。

# 查看自己的 npm 版本
$ npm --version

# 第一種新建項(xiàng)目方式——npm 5.2+ 時(shí)搏色,以下命令會(huì)安裝最新版 CRA
$ npx create-react-app my-app
# 第一種新建項(xiàng)目方式——npm 版本小于等于 5.1 時(shí)
$ create-react-app my-app

# 第二種新建項(xiàng)目方式
# npm 6+ 開始支持 npm init <initializer> 
$ npm init react-app my-app

# 第三種新建項(xiàng)目方式
$ yarn create react-app my-app

項(xiàng)目的文件結(jié)構(gòu)

通過命令行的構(gòu)建,我們初始化了第一個(gè) CRA 項(xiàng)目券册,其中幫我們生成的項(xiàng)目目錄結(jié)構(gòu)如下(只有 src 下的文件才會(huì)被 Webpack 處理频轿,只有 public 下的文件才能被 public/index.html 使用):

my-app
├── .git # 隱藏文件夾,會(huì)初始化第一個(gè) Commit 記錄
├── README.md
├── node_modules
├── package.json # 依賴配置文件
├── .gitignore
├── [floder_name] # 根目錄下可以建立其他文件夾烁焙,但不會(huì)被用在生產(chǎn)環(huán)境中
├── public # 只有 public 下的文件才能被 public/index.html 使用
│   ├── favicon.ico
│   ├── index.html # public/index.html 頁面模板
│   └── manifest.json
└── src # 只有 src 下的文件才會(huì)被 Webpack 處理
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── [floder_name] # 可以建立其他文件夾航邢,以被 Webpack 成功導(dǎo)入
    ├── index.css
    ├── index.js # JavaScript 打包入口文件
    ├── logo.svg
    └── serviceWorker.js

關(guān)于 package.json、index.js 和 public/index.html 文件夾骄蝇,我們通過“實(shí)戰(zhàn) 2”已經(jīng)有所了解膳殷。前者是 JavaScript 打包入口文件,通常鏈接整個(gè)業(yè)務(wù)代碼乞榨;后者是頁面模板秽之,是打包后整個(gè)靜態(tài)頁面的總?cè)肟凇?/p>

這里對(duì)以下兩個(gè)文件的出現(xiàn)進(jìn)行簡(jiǎn)要的意義概括。<br />_

  • src/serviceWorker.js:提供漸進(jìn)式 Web 應(yīng)用的核心功能吃既,不論網(wǎng)絡(luò)狀況如何都能立即加載考榨,并且在不需要網(wǎng)絡(luò)請(qǐng)求(離線時(shí))的情況下也能展示 UI ;
  • public/manifest.json:是漸進(jìn)式 Web 應(yīng)用將自身添加至桌面的功能依賴文件鹦倚,也可以對(duì)圖標(biāo)河质、名稱等信息進(jìn)行配置。

運(yùn)行 CRA 項(xiàng)目

CRA 默認(rèn)提供了運(yùn)行震叙、測(cè)試掀鹅、打包、部署以及彈出項(xiàng)目的命令媒楼。其中的一些貼士:

  • npm start 內(nèi)置熱更新機(jī)制乐尊,代碼改動(dòng)時(shí)頁面自動(dòng)刷新;
  • npm test 以交互方式運(yùn)行測(cè)試觀察程序划址,默認(rèn)情況下運(yùn)行與自上次提交以來更改的文件相關(guān)的測(cè)試扔嵌;
  • npm run build 將要生產(chǎn)的應(yīng)用程序生成到生成文件夾。它在生產(chǎn)模式下正確捆綁了React夺颤,并優(yōu)化了構(gòu)建以獲得最佳性能痢缎。生成文件被壓縮,并且文件名包含哈希世澜;
  • npm run eject 將內(nèi)置的各種 Webpack 配置彈出到項(xiàng)目中独旷,讓我們可以進(jìn)行自定義。同時(shí)此操作不可逆寥裂,意味著我們承擔(dān)了彈出配置后的風(fēng)險(xiǎn)嵌洼。通常不推薦彈出,可以通過 React App Rewired 庫進(jìn)行配置注入封恰。
# ---- 運(yùn)行 ----
$ npm start
$ open http://localhost:3000
# ---- 測(cè)試 ----
$ npm test
# ---- 打包 ----
$ npm run builds
# ---- 彈出配置 ----
$ npm run eject

搭建 CRA 生態(tài)

根據(jù)官方文檔的思路咱台,我們還能從更多角度拓展 CRA 的使用邊界,下面進(jìn)行概要介紹俭驮。

  • 為開發(fā)環(huán)境添加額外功能:包括“配置編輯器風(fēng)格”回溺、“開發(fā)隔離組件”、“分析打包文件”和“添加 HTTPS 支持”混萝;
  • 添加樣式與靜態(tài)資源支持:包括“添加樣式表文件”遗遵、“添加 CSS Modules 支持”、“添加 Sass 支持”逸嘀、“添加 PostCSS 支持”车要、“添加圖片文字和字體支持”、“添加 GraphQL 支持”崭倘、“使用 public 文件夾”翼岁、“進(jìn)行代碼拆分”类垫;
  • 添加業(yè)務(wù)驅(qū)動(dòng)支持:包括安裝各種依賴項(xiàng)如“BootStrap”、“Flow”琅坡、“TypeScript”悉患、“Delay”、“Router”榆俺,以及“導(dǎo)出組件”售躁、“使用全局變量”、“配置環(huán)境變量”茴晋、“制作漸進(jìn)式 Web 應(yīng)用”和“創(chuàng)建生產(chǎn)環(huán)境”陪捷;
  • 添加測(cè)試支持:包括“運(yùn)行測(cè)試”和“調(diào)試測(cè)試”;
  • 添加后端集成支持:包括“在開發(fā)環(huán)境中代理 API 請(qǐng)求”诺擅、“使用 AJAX 請(qǐng)求獲取數(shù)據(jù)”市袖、“集成后端 API”和“使用 Title & Meta 標(biāo)簽”;
  • 部署進(jìn)階:包括“靜態(tài)服務(wù)器”烁涌、“Azure”凌盯、“Firebase”、“Github Pages”等平臺(tái)的部署等烹玉。

這里無法深入展開驰怎,每一個(gè)點(diǎn)都可以是一個(gè)新的實(shí)戰(zhàn),當(dāng)我們需要某個(gè)功能時(shí)便可以查閱相關(guān)文檔來主動(dòng)探索二打。其中“分析打包文件”的解讀見“實(shí)戰(zhàn) 4”县忌。

實(shí)戰(zhàn) 4:使用 Source Map Explorer 分析打包文件

# 安裝文件分析工具 source-map-explorer
$ sudo npm install --save source-map-explorer
# 打包項(xiàng)目
$ npm run build
# 將如下命令放入 package.json 中并生成快捷方式 npm run analyze
# $ source-map-explorer 'build/static/js/*.js'
# 注意此命令直接在命令行輸入會(huì)提示找不到相關(guān)命令
$ npm run analyze

對(duì)于一個(gè)剛被 CRA 生成的 React App 來說,分析的結(jié)果如下继效,包大總計(jì) 129.38k症杏。

實(shí)戰(zhàn) 5:在已有的 React 項(xiàng)目中引入/升級(jí) CRA

回到剛才“實(shí)戰(zhàn) 2”建立的 react-webpack-steper 項(xiàng)目中,當(dāng)我們已經(jīng)編寫了一部分業(yè)務(wù)時(shí)瑞信,能否直接在當(dāng)前項(xiàng)目中無痛引入 CRA厉颤?

解決思路便是:在大多數(shù)情況下,更改 package.json 中的 react-scripts 版本并刪除不必要文依賴配置凡简,接著在此文件夾中運(yùn)行 npm install 就足夠了逼友,但最好參考更改日志以了解潛在的重大更改。CRA 致力于將重大更改保持在最低限度,以便可以輕松升級(jí) React 腳本。

# 卸載 CRA 本身已經(jīng)提供的依賴
$ 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
# 手動(dòng)安裝 React Script
$ sudo npm install --save react-scripts@latest
# 由于 CRA 默認(rèn)規(guī)則痛单,將 src/index.html 移至 public/index.html
$ mkdir public
$ mv src/index.html public
# 在 package.json 中添加 React Script 啟動(dòng)命令
$ vim package.json

package.json 中添加/覆蓋如下指令。

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",

再次執(zhí)行即可驯嘱。由于每個(gè)人的具體配置不一定一致,可根據(jù)自身所遇問題進(jìn)行搜索疏魏。升級(jí)原理類似倒信。

# 當(dāng)沒有 BrowsersList 時(shí)照棋,CRA 會(huì)進(jìn)行詢問并幫助我們生成
$ npm start

實(shí)戰(zhàn) 6:使用 React App Rewired 注入新配置

CRA 官方并不推薦使用 npm run eject 彈出配置资溃,這會(huì)增加更多的 Webpack 維護(hù)工作。對(duì)于實(shí)在想改的 Webpack 配置來說烈炭,我們可以使用 React App Rewired 庫進(jìn)行配置注入溶锭,這里來做個(gè)小例子。

此工具可以在不 'eject' 也不創(chuàng)建額外 react-scripts 的情況下修改 create-react-app 內(nèi)置的 webpack 配置梳庆,然后你將擁有 create-react-app 的一切特性,且可以根據(jù)你的需要去配置 webpack 的 plugins, loaders 等卑惜。

繼續(xù)使用 react-webpack-steper 項(xiàng)目膏执,我們的簡(jiǎn)易目標(biāo)是增加 devServer 本地代理。

第一步:安裝依賴并進(jìn)行基礎(chǔ)配置

# 安裝依賴
$ sudo npm install --save-dev react-app-rewired customize-cra
# 根目錄建立 config-overrides.js
$ touch config-overrides.js
# 修改 package.json
$ vim package.json
# 運(yùn)行項(xiàng)目
$ 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"
}

第二步:編寫配置更米,進(jìn)行代理

# 新增配置文件
$ 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
  }),
}

此時(shí)毫痕,本地的所有 api 開頭的接口請(qǐng)求都會(huì)被轉(zhuǎn)發(fā)到 http://110.114.120.120:8080 的模擬后端 IP 上征峦。

對(duì) CRA 未來版本的簡(jiǎn)單展望

截止目前(2020-01-10),CRA 的最新版本是 v3.3.0消请,我們可以從 Github 的 MileStone 中看到未來可能會(huì)改善的功能栏笆,其中整理并如下所述。

  • v3.x:添加多入口文件支持(不只是一個(gè) index.js 入口)臊泰;使用 worker-loader 添加對(duì) WebWorker 的支持蛉加;更早地檢查 Node 的版本;添加對(duì)子資源完整性 SRI 支持缸逃;生產(chǎn)環(huán)境中預(yù)加載腳本和鏈接...
  • v4.0:支持 Webpack 5.0(Webpack 目前最新版 v4.41.5针饥,v5 也推出了一年多內(nèi)測(cè)版);在 tsconfig.json 和 jsconfig.json 里新增對(duì) baseUrl 和 paths 的支持(方便寫 @ 絕對(duì)路徑等)需频;支持 Jest 配置中設(shè)置browser 為 true(根據(jù)環(huán)境提供正確的 Node 或 Browser 模塊)...
  • v100.0:提供構(gòu)建過程中的監(jiān)視模式丁眼;適用于 Hooks 的熱加載...

讓我們一起持續(xù)關(guān)注。

結(jié)語

回顧文章昭殉,我們從初始化 React App 的多種方式苞七,引出 CRA 的必要性再對(duì)其進(jìn)行較為充分的解釋,最后配上 6 個(gè)角度來從一些角度對(duì) CRA 的使用方式進(jìn)行了實(shí)戰(zhàn)挪丢,最后回歸到 CRA 的版本展望之中莽鸭。

感謝你的閱讀,如果你有什么更多的疑惑吃靠,CRA 的官方文檔 + 開源倉庫一定會(huì)滿足你的一切硫眨。

最后,一起拜讀一下 CRA 和 Redux 作者、React 的核心貢獻(xiàn)者 Dan Abramov 發(fā)布的這篇“我的十年回顧”文章礁阁。

現(xiàn)在我們可以開始正式深入地學(xué)習(xí) React 技術(shù)棧了巧号。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市姥闭,隨后出現(xiàn)的幾起案子丹鸿,更是在濱河造成了極大的恐慌,老刑警劉巖棚品,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件靠欢,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡铜跑,警方通過查閱死者的電腦和手機(jī)门怪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锅纺,“玉大人掷空,你說我怎么就攤上這事《陲保” “怎么了坦弟?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)官地。 經(jīng)常有香客問我酿傍,道長(zhǎng),這世上最難降的妖魔是什么驱入? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任拧粪,我火速辦了婚禮,結(jié)果婚禮上沧侥,老公的妹妹穿的比我還像新娘可霎。我一直安慰自己,他們只是感情好宴杀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布癣朗。 她就那樣靜靜地躺著,像睡著了一般旺罢。 火紅的嫁衣襯著肌膚如雪旷余。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天扁达,我揣著相機(jī)與錄音正卧,去河邊找鬼。 笑死跪解,一個(gè)胖子當(dāng)著我的面吹牛炉旷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼窘行,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼饥追!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起罐盔,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤但绕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后惶看,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捏顺,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年纬黎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幅骄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡莹桅,死狀恐怖昌执,靈堂內(nèi)的尸體忽然破棺而出烛亦,到底是詐尸還是另有隱情诈泼,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布煤禽,位于F島的核電站铐达,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏檬果。R本人自食惡果不足惜瓮孙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望选脊。 院中可真熱鬧杭抠,春花似錦、人聲如沸恳啥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钝的。三九已至翁垂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間硝桩,已是汗流浹背沿猜。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碗脊,地道東北人啼肩。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親疟游。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呼畸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355