寫在前面:
- 以下create-react-app以下簡稱CRA
- 本文均使用yard進行包安裝及專案啟動和打包,喜歡使用npm的同學,可自行換成npm命令
- 本專案實現了基於CRA2.x搭建的基本專案框架,並實現了一個仿騰訊天氣的頁面
- 本文的基礎框架搭建可用於基於企業級後臺管理系統搭建
- 筆者搭建環境macOS Mojave10.14.1,node版本8.12.0,IDE是VSCode
- 前期準備需要node環境,node環境準備請自行搜尋,這個不在本文說明範圍內
- 如果是CRA或者React初學者,請務必在GitHub上clone原始碼對照文章進行學習
- 本專案旨在記錄CRA2.x企業級專案框架搭建過程,順便在閒暇時間寫了一個仿騰訊天氣的頁面,主要為了實際在專案中運用antd,mobx和echarts-for-react這三個很重要的庫的使用
- 本文所有環節都有註明必學還是選學,有基礎的讀者權當參考,若無基礎的讀者,請無比在GitHub上clone程式碼,對照文章進行學習(再次強調!)
- 本專案GitHub地址
- 本專案DEMO (ps.專案最主要的bug在於伺服器,因為天氣預報系統,用到了ip定位,我在開發階段使用了proxy配置的代理,沒有問題,但是掛載到nginx伺服器上的時候,每次預設通過ip定位,都定位到北京去了,我查閱了很多資料,有解決辦法,但是需要後端配合,但是我的後端又是第三方的api,這個問題感覺有點無解...如果有解決辦法的同學或者有其他交流想法的同學,歡迎給我提issues,或給我留言,大家一起交流)
- 因為第三方api有訪問流量限制,如果訪問過量,可能存在頁面無法開啟的情況,如果無法開啟demo了,請及時與作者聯絡
1. 開啟CRA之路 (必學步驟)
意義說明:這是專案搭建準備的基礎中的基礎
腳手架工具 create-react-app
,CRA詳細介紹可以檢視 Github CRA連結
使用腳手架的步驟:
npx create-react-app my-app
cd my-app
確認專案執行沒有問題
yarn start
開啟自定義webpack配置
yarn eject
or npm run eject
可以看到多了幾個檔案,並且package.json裡面多了很多內容,這些就是CRA內部封裝的配置,暴露出來了,這個操作是不可逆的,這個操作的意義就在於我們可以自行修改webpack配置以及全域性變數等配置,這對於一個企業級開發框架來說,是必要的
2. cross-env及全域性變數配置 (必學步驟)
意義說明:這節內容是為了解決跨平臺開發和靈活應對不同上線需求的(測試環境、預釋出環境、正式環境等)
(1)cross-env,用於解決統一mac和windows專案執行的問題,大多數情況下,在windows平臺下使用類似於: NODE_ENV=production的命令列指令會卡住,使用cross-env可以讓不同平臺使用唯一指令,無需擔心跨平臺問題
安裝cross-env yarn add cross-env --dev
配置package.json如下
cross-env
即可,我這裡有三個命令,start不用說,就是執行開發環境,"build:test"和"build:production"是幹什麼的呢,另外cross-env後面跟的一大堆引數是什麼意思呢,這個我會在下面進行詳細說明
(2)配置全域性變數檔案
全域性變數檔案,通常,我們會把api請求的伺服器地址,某些固定請求字首,特定appId,釋出地址,api伺服器地址,等相關引數寫到全域性變數中,我們通過全域性變數檔案,可以很方便的達到在開發和打包各個環境時,區分開不同的全域性變數(比如開發環境請求的api字首是http://xxxx-test.xxx,而正式環境是http://xxxx-pro.xxx),在企業級前端開發專案中,全域性變數檔案是必須的
我的專案就區分了三個全域性變數,包括.env.development .env.test .env.production,分別用於表示開發環境,測試環境打包,正式環境打包
-
配置 全域性變數檔案必須以.env.xxx的格式命名,放置在專案根目錄下,常用的就是development(開發環境),test(測試釋出環境),production(正式生產環境)
-
檔案格式:".env.xxxx" 這裡的xxx可以自定義想要的名字,但是通常都是上面這三個,現在我們回到package.json中看,也就是上面那張“cross-env配置截圖”,在scripts中每個命令中有一個引數就是RECORD_ENV=xxxxx,這個xxxxx就是對應的全域性變數的字尾檔名,表示在執行start命令的時候RECORD_ENV環境是development,其他同理,接下來就修改根目錄下config資料夾裡面的env.js檔案,這裡面就有我們讀取全域性檔案的程式碼
這裡需要我們將
const NODE_ENV = process.env.NODE_ENV;
改為const NODE_ENV = process.env.XXXX;
,這裡的XXXX就是我們在package.json的scripts中,每條執行命令的那個區分環境的引數,我用的就是RECORD_ENV -
全域性變數檔案中變數命名格式: 必須是“REACT_APP_XXX”這樣的格式,對應的各個不同環境下的全域性變數檔案各自命名各自所需的全域性變數,寫好每個檔案中的所需變數後,我們就完成了全域性變數配置
特別說明1: 關於第二步cross-env及全域性變數配置,這一步不是執行基礎框架所必須的,因為一般來說個人專案不會存在多環境下,環境變數不同的問題,但是對於企業級專案框架搭建來說,這個配置卻是必須的,因為後端一定會存在測試環境,開發環境的區別
特別說明2: 關於內建環境變數的說明:我們修改了env.js中的配置,細心的同學肯定會發現到處都出現了這個變數“NODE_ENV”,下面我就簡單說明一下CRA的內建的環境變數 create-react-app內建有兩個環境變數,PUBLIC_URL和NODE_ENV PUBLIC_URL是靜態資源的釋出路徑,在public/index.html有使用,這個預設值是'',需要自己進行配置 NODE_ENV有三個值,分別對應如下: npm start => development npm test => test npm run build => production NODE_ENV的值不能手動進行覆蓋,所以需要我們手動設定一個新的環境變數名稱,然後在scripts執行命令的時候,通過指定環境引數來指定當前的環境變數檔案,這就是我們上面“修改env.js檔案配置”截圖所做的事情
3. 配置ESLint和prettier (選學步驟)
意義說明:這節內容是為了配置團隊開發的時候的程式碼規範,作為一個企業級的前端專案架構,團隊協作開發是必不可少的,但如果認為沒有必要的同學,也可直接跳過本章節,程式碼規範檢測及配置,並不是專案執行所必須的配置
首先,我們需要安裝prettier,yarn add prettier --dev
prettier是業內常用的格式化程式碼的工具庫,筆者用的IDE是VSCode,VSCode有預設的格式化程式碼的規範,但是沒有prettier好用,也可以在VSCode的外掛庫庫裡面直接安裝prettier外掛
關於ESLint,我們的CRA框架預設配置,已經預裝了ESLint了,我們只需要選擇想用的規則即可,這裡我選的是這裡我們使用airbnb的標準程式碼格式規範,業內比較常用的就是airbnb和standard這兩個規範,具體相關知識,這裡不做贅述,讀者可以自行搜尋比較
安裝airbnb規則外掛yarn add eslint-config-airbnb --dev
airbnb是我們主要的程式碼檢測規則
安裝prettier規則外掛yarn add eslint-config-prettier --dev
eslint-config-prettier可以解決eslint和prettier對於同一個錯誤多次報錯的問題
安裝prettier在eslint下的外掛yarn add eslint-plugin-prettier --dev
eslint-plugin-prettier會讓eslint呼叫prettier對你的程式碼風格進行檢查
配置ESLint規則檔案
eslint --init
可以根據嚮導一步一步建立配置檔案,也可以直接在根目錄下建立幾種配置檔案的格式,我常用的就是.eslintrc.json,配置檔案詳細內容,請讀者自行搜尋,這裡我只說明我配置的
.eslintrc.json 放在根目錄下 用於遮蔽不需要的eslint規則 .eslintignore 用於遮蔽不需要eslint檢測的資料夾,一般是node_modules,webpack配置檔案等,這些資料夾是不需要eslint檢測的
eslintrc.json具體內容配置說明: .eslintignore具體內容配置說明:最後,使用各大IDE的讀者們,應該現在所有的IDE都有了ESLint和prettier的外掛,這些外掛都是依賴於node_modules裡面的原始碼庫的,外掛只是IDE整合了這兩個庫的一個使用的入口,建議都把這兩個庫的外掛安裝好,然後重啟IDE
到這裡,我們關於ESLint和prettier外掛的配置就完成了
特別說明: 禁用規則:因為airbnb是比較嚴格的規範,但是還是有不少規則,其實在實際開發中,會存在不少的麻煩的,我遮蔽了以下規則,具體規則意義可以自行查閱相關文件 "prettier/prettier": "error", "import/no-unresolved": 0, "react/forbid-prop-types": 0, "prefer-destructuring": 0
4. 安裝lodash (選學步驟)
**意義說明:**如果不熟悉lodash的同學可以跳過本步驟,lodash是業內較為常用的一個JS庫,裡面包含了很全面的封裝方法,但其實大部分人實際開發的時候,用JS的內建方法也基本都能滿足需求了,用lodash只是圖一個簡潔方便,所以就是筆者個人比較喜歡用lodash的清爽直接,所以安裝了
安裝 yarn add lodash
5. 安裝less相關,webpack配置less支援 (選學步驟)
意義說明:這節內容是為了給專案新增less支援,我們在實際開發中,通常都是以下圖這樣來使用less樣式的,對於less不瞭解的讀者,可以自行學習一下less,企業級的專案架構中,肯定都是使用less或者sass的,筆者一直接觸的都是less,sass的配置還請讀者自行研究,這裡我們只講less的配置
首先安裝less模組支援
yarn add less --dev
yarn add less-loader --dev
然後分別在根目錄下的config/webpack.config.dev.js和config/webpack.config.prod.js檔案中配置
config/webpack.config.dev.js檔案
-
第一步修改
注意:很多相關文件沒有javascriptEnabled: true
這句程式碼,是因為less在3.x版本及以上,會需要加上這句話,否則會報錯,除非安裝less3.x以下的版本 -
第二步修改
注意:這一步修改的意義在於處理node_modules不需要開啟css模組化,也就是我們上面的貼圖“less在專案中的使用”這樣的使用,所以有這樣一句,include: [/node_modules/]
,然後處理本地自己開發的程式碼的時候,需要加上css模組化配置,否則無法使用import styles from 'xxxx'
這樣的用法,所以下面處理本地less的時候,加上了exclude: [cssModuleRegex, /node_modules/]
,這個cssModuleRegex是CRA2.x預設存在的配置,不用動就是了
config/webpack.config.prod.js檔案 這個檔案表示打包時候執行的webpack配置,和config/webpack.config.dev.js略有不同,但是新增對less支援這塊的配置,是一模一樣的配置,這裡就不贅述了
6. 安裝antd,配置antd按需載入,安裝mobx mobx-react,修改babel配置 (必學步驟)
意義說明:這節內容是為了新增antd的框架,mobx mobx-react,並新增按需載入配置,關於這塊內容,官網有更為詳細的介紹,讀者也可以參考官網的說明antd官網 ,另外本步驟會詳細說明一下CRA2.x已經預裝到了babel7,有很多配置和以前不一樣,建議仔細閱讀本步驟 必學步驟
安裝antdyarn add antd
安裝antd按需載入必備元件yarn add babel-plugin-import --dev
安裝mobxyarn add mobx
安裝mobx-reactyarn add mobx-react
首先展示我的.babelrc檔案配置 CRA預設的babel配置是放在了package.json裡面,這裡我將package.json裡面的babel配置刪除,單獨在根目錄下建立了一個.babelrc檔案,個人覺得單獨配置會比較清晰一些
babel-plugin-import實現按需載入
如上圖展示,在plugins中新增[ "import", { "libraryName": "antd", "style": true } ],
新增對ES7修飾器語法支援
如上圖展示,在plugins中新增["@babel/plugin-proposal-decorators", { "legacy": true }]
,修飾器用法是mobx的用法中,最簡單直觀的,推薦使用mobx的框架都應該使用修飾器的用法
多說一句1
如果你的babel版本是7以下,name就需要先安裝 yarn add transform-decorators-legacy --dev
,然後在plugins中新增配置transform-decorators-legacy
即可,但是CRA2.x已經將babel升到了7了,如果你還按照舊的配置方法,會有如下報錯
解決babel 7報錯問題
CRA2.x安裝的babel版本已經達到7以上了,使用transform-decorators-legacy會有以下報錯
The ‘decorators’ plugin requires a ‘decoratorsBeforeExport’ option, whose value must be a boolean. If you are migrating from Babylon/Babel 6 or want to use the old decorators proposal, you should use the ‘decorators-legacy’ plugin instead of ‘decorators’
github.com/mobxjs/mobx…
多說一句2
如上面所說,可能有的文章是CRA1.x的版本,會說需要npm i transform-decorators-legacy
來支援對修飾器的用法,但基於CRA2.x搭建的框架其實不需要了,因為CRA2.x已經預裝到了babel7,babel7對修飾器的支援包已經換為了“@babel/plugin-proposal-decorators”這個包,配置也改成這樣的配置["@babel/plugin-proposal-decorators", { "legacy": true }]
,這裡你可以自己試一下,單獨開一個檔案,yarn add babel-preset-react-app
,對,關鍵就是這個babel-preset-react-app,這個是CRA預裝的“一條龍”包,裡面包含了大量可能用的到的外掛包,在CRA建立你的專案的時候,就已經給你裝好了的,其中就已經包括了我們需要在.babelrc裡面新增的@babel/plugin-proposal-decorators 對修飾器支援的包,這也就是babel配置裡面的第一句"presets": ["react-app"]
,這裡的意思就預裝使用babel-preset-react-app這個包的內容
這個庫已經涵蓋了很全面的babel配置外掛了,這個庫把我們常用的比如@babel/preset-env(適配各版本的babel轉換) @babel/plugin-proposal-class-properties(對class語法的轉換) @babel/plugin-transform-runtime(執行時轉換) 等等都已經封裝進去了,所以我們這裡唯一需要新增的支援就是對修飾器的配置
然後有的讀者可能就有疑問了,既然babel-preset-react-app預裝包已經包含了我們需要用到的@babel/plugin-proposal-decorators,那麼為什麼我們還要再plugins裡面新增這一句話呢,是因為在babel-preset-react-app的原始碼中,對於@babel/plugin-proposal-decorators的開啟有一句程式碼,是必須要傳入"typescript:true"這句配置,這裡我理解,可能對於使用typescript的專案,在babel中加入這樣的配置,"presets": [["react-app",{typescript:true}]]
才會開啟修飾器支援的包,但事實上我已經試過了,執行專案還是會報錯,這裡就要說到正確的配置["@babel/plugin-proposal-decorators", { "legacy": true }]
這裡來了,我理解的"legacy": true
,就是舊版本的修飾器支援,而新版本的修飾器庫還不支援mobx的用法,所以如果不新增"legacy": true
,則還是會報錯。
正確解決修飾器使用問題,及擴充說明
我們的報錯內容有一個關鍵字“decoratorsBeforeExport”,decoratorsBeforeExport這個引數是最新的修飾器外掛所必須的一個引數,但官方也還在社群徵集意見到底採用decoratorsBeforeExport:true
or decoratorsBeforeExport:false
,所以現階段各位同學只需要使用legacy:true
即可,這個是babel官方說明
其實這個引數的true or false就是兩種格式的爭論,有興趣的同學可以圍觀,關於這個引數的詳細討論連結在這裡
7. react-router4.x使用及路由按需載入 (必學步驟)
安裝 yarn add react-router-dom
react-router-dom是基於react-router的,比react-router多了一些DOM類的元件,比如 這樣的元件,瀏覽器開發直接安裝react-router-dom即可
關於react-router4.x的詳細用法,又可以單獨寫一篇文章了,這裡我不做詳細的講述,本文的主旨是專案架構,這裡我只貼出自己的寫法,寫一些簡單的用法,看貼圖不清楚的同學,可以把專案clone下來仔細檢視
index.jsx檔案
app.jsx檔案
routers.jsx檔案
按需載入(重點,路由的按需載入是前端優化的必須步驟,按需載入,顧名思義,頁面在載入時只請求當前路由所需的資源,而不會全部路由資源都給請求下來,如果不配置按需載入,在後期專案龐大之後,會非常影響使用者體驗)
按需載入的配置文章,在網上也有很多,這裡我只介紹兩種,是我個人覺得比較輕量簡單的兩種方法,方法不止這兩種,讀者可自行搜尋,詳細瞭解原理
- react-loadable(按需載入的一個支援庫)
安裝
yarn add react-loadable
使用import Loadable from 'react-loadable';
const MineItem = Loadable({ loader: () => import('./pages/mine'), loading: MyLoadingComponent });
截圖: - 自定義Bundle.js元件,路由元件用這個Bundle套在外層 截圖:
8. 安裝axios (必學步驟)
意義說明:axios和fetch是業內常用的兩個api請求庫,筆者都有用過,總的來說axios更簡單輕量,具體的用法和比較,請讀者自行思考了
安裝yarn add axios
axios的基本使用,請讀者自行檢視axios中文文件,這裡我只提一個我專案中用到的配置,就是axios的攔截配置,axios可以攔截請求,返回的資料,提前做一些處理,比如:
配置好axios攔截器後,直接在在index.js中匯入這個攔截器檔案就好了
9. 圖表庫 (選學步驟)
意義說明:企業級專案中,不可能不用到視覺化圖示的庫的,這裡作為個人學習,可以不需要安裝,但是筆者的框架內實現了一個仿騰訊天氣的頁面,用到了echarts-for-react,這個讀者根據需要,自行判斷是否需要
安裝yarn add echarts-for-react
多說一句 關於圖表庫,不做多的贅述,業界內用到圖表庫的時候,最常用的兩個就是d3和echarts,echarts-for-react只是這個作者基於echarts封裝了一個統一的react元件,api的使用,就直接檢視echarts官方api文件即可,沒有任何的變化,關於d3和echarts的比較使用,可以檢視這篇文章,使用者可自行比較 echarts官方文件 echarts-for-react,
10. 前端開發環境的跨域代理配置 (必學步驟)
意義說明:跨域是每個前端工程師必備的基本功之一,對於跨域筆者不做多的介紹了,企業級專案的跨域多數都是採用的CORS跨域方法,這個主要的配置是在服務端,而筆者這裡介紹的是一種在前端進行跨域的方法,像筆者這樣的個人專案搭建,又用的是第三方的api,服務端的設定我肯定是改不了了,所以就用的前端代理的方法,配置方法非常簡單
只需要在package.json中加上"proxy": "http://xxxxxx"
即可,xxxx就是代理伺服器的地址
多說一句 筆者使用CRA1.x搭建專案的時候,proxy還可以像下面這樣配置
這樣配置的好處是可以多api服務的跨域,比如定位api用的是百度的,其他api又用的是高德的,就可以採用這樣的配置,但是CRA2.x搭建後,我這樣配置了,**執行的時候給我報錯,提示我proxy只能是一個字串,**截止目前,我暫時還沒有找到解決的辦法,不過因為我這個專案只用到了一個地址的第三方api,所以執行我的專案,也不存在這個問題,然後實際開發中,多數都是服務端使用CORS跨域,可能也不太會遇到這個問題,這個我後面如果解決了,會更新到文章中的11. nginx準備 (選學步驟)
意義說明:這節內容是屬於折騰伺服器的範疇了,我不準備在這篇文章內進行詳細的介紹,我的下一篇文章,會介紹我折騰nginx伺服器的正確步驟以及踩坑點,下面列出的是一些需要配置的東西,有興趣的讀者可以自行在網上查詢資料學習 系統:伺服器系統準備 centos7.2 nginx相關安裝(很多依賴庫) nginx反向代理設定(用了第三方的api,必須要配置nginx的反向代理,否則api啥都訪問不到,如果是自己寫的後端,可以配置使用CORS跨域,就不用配置反向代理了) nginx gzip壓縮配置(大幅增加頁面載入速度,啟用gzip將我的應用從15s減少到4.x秒,這裡又提到上文所說的路由按需載入,路由按需載入配置和gzip壓縮,是前端工程師必須知道或者瞭解的兩個優化方法,可以大幅加快頁面載入速度)
寫在後面
筆者實現的仿騰訊天氣的頁面目最主要的bug在於伺服器,因為天氣預報系統,用到了ip定位,我在開發階段使用了proxy配置的代理,沒有問題,但是掛載到nginx伺服器上的時候,每次預設通過ip定位,都定位到北京去了,我查閱了很多資料,有解決辦法,但是需要後端配合,但是我的後端又是第三方的api,這個問題感覺有點無解...如果有解決辦法的同學或者有其他交流想法的同學,歡迎給我提issues,或給我留言,大家一起交流成長
最後,如若文章有任何錯誤或者誤導讀者的地方,請立即與作者聯絡,這是作者第一次發框架搭建性質的指導文件,難免存在遺漏和模糊不清的地方(亦或是寫了太多作者自己理解的東西了,讓讀者看的比較迷茫????),都請大家多多見諒。