本文差點(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í)更多。以下是官方源碼倉庫以及官方文檔地址:
- Github 地址:https://github.com/facebook/create-react-app
- 官方文檔地址:https://create-react-app.dev

初始化 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)的 ServiceWorker 和 Web 應(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)考慮使用更靈活的 nwb 或 Neutrino。特別是對(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.js 或 Razzle啄糙。 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ī)則如下:
- 該項(xiàng)目支持最新 JavaScript 標(biāo)準(zhǔn)的超集评腺。 除ES6語法功能外,它還支持:
- Exponentiation Operator (ES2016)淑掌;
- Async/await (ES2017)蒿讥;
- Object Rest/Spread Properties (ES2018);
- Dynamic import() (stage 4 proposal)抛腕;
- Class Fields and Static Properties (part of stage 3 proposal)芋绸;
- JSX, Flow and TypeScript;
- Learn more about different proposal stages担敌。
- 盡管 Facebook 建議謹(jǐn)慎使用實(shí)驗(yàn)性功能摔敛,但 Facebook 會(huì)在產(chǎn)品代碼中大量使用這些功能,因此全封,如果將來任何這些建議發(fā)生更改马昙,F(xiàn)acebook 都打算提供 codemod桃犬;
- 請(qǐng)注意,默認(rèn)情況下行楞,該項(xiàng)目不包含任何 polyfill攒暇;
- 如果您使用任何其他需要運(yùn)行時(shí)支持的ES6 +功能(例如Array.from()或Symbol),請(qǐng)確保手動(dòng)包括適當(dāng)?shù)膒olyfill子房,或者您要定位的瀏覽器已支持它們形用。
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ù)棧了巧号。