webpack工程化整合React技術棧(一)

jasonlive發表於2019-02-27

專案開始前,我們先聊一聊關於專案的一些說明。該專案起始於2017年初,當時公司主要技術棧為gulp+angular,鑑於react的火熱的生態,在公司決定研發bss管理系統時選用react開發,目的也是為react native打下基礎,以解決後期公司大前端技術棧的逐步成熟。(當時沒有選擇vue開發的主要原因是weex生態還不夠特別成熟),既然決定換新,專案的構建也跟著一起換,從gulp轉向火熱的webpack,持續大半年的更新迭代,我們將構建模組逐步從專案中抽離出來,把構建模組作為npm包單獨管理,完成和專案程式碼解耦,於是就有了後面我們要說的wci-build構建模組包和wci-cli專案腳手架。

我們要做什麼

技術棧

專案採用前後端分離的形式,後端選用Maven+SpringClould全家桶開發,前端選用webpack+react全家桶開發,前後端全部採用包管理工具完全解決專案依賴管理的難題,版本管理採用git,前後端通過json互動,swgger管理介面文件,介面全部遵循restful規範。由於本文面向社群開放,故本文中不涉及公司業務層的程式碼,本文全部程式碼均為最新編寫,我們以一個旅遊管理系統的三個模組為大家演示專案(登陸登出、使用者模組、景點模組)。為了快速開展,本文涉及的後端程式碼直接採用Java的SSM框架搭建,原始碼也將為大家奉上。朋友們也可以使用mock模擬介面資料。後期我們在演示nodejs+espress時將介面程式碼全部轉為node形式。

準備

因本文不是講解基礎,故大家在敲程式碼前,還需要具備一定的前端基礎,部分如下

  1. html、css、javascript基礎知識
  2. es6基礎知識
  3. react基礎知識
  4. 瞭解什麼是webpack、babel、redux、react-router、nodejs、npm
  5. 熟悉螞蟻金服ant design
  6. 熟悉less基本使用

解決什麼問題

本專案整合了最新的react16、react-router4、redux,同時可以選擇性整合antd|antd mobile,在解決繁瑣的架構配置工作外,還解決了以下問題

通用問題
  1. 支援開發效率更高的ES6編寫程式碼。
  2. 拆分開發、測試、生產環境,完成從開發到上線的所有工作。
  3. 開發環境包含熱替換,本地IP、埠可配置,介面可配置,微服務模組可配置
  4. 測試環境包含程式碼壓縮、合併、css抽離、公共元件抽離、程式碼新增hash、測試版本字尾
  5. 生產環境包含程式碼壓縮、合併、css抽離、公共元件抽離、程式碼新增hash、生產版本字尾(和測試程式碼完全一樣,只缺少測試版本號)
  6. 支援自定義新增webpack loader
其他問題
  1. 目前大型專案後端多采用微服務架構,API介面在開發、測試、生產環境下來回切換,需要頻繁修改程式碼。解決方案:通過配置檔案的方式統一配置專案模組介面
  2. 專案模組在分拆開發的過程中css命名衝突,導致程式碼維護性較差。解決方案:構建工具預載入css時自動化新增hash,使css程式碼模組化
  3. 不同開發人員,不同的程式碼習慣造成專案程式碼難以維護。解決方案:在程式碼編寫、構建、版本管理三個方向加入程式碼規範校驗(airbnb規範)
  4. 在同時開發多個系統的時候,構建業務模組在不同的專案都存在,當需要修改配置或者優化構建方案的時候,需要修改多個專案的配置。解決方案:抽離構建模組,採用npm形式依賴。

還有什麼問題要解決

雖然經過大半年迭代,但我們還需要在實際專案開發中支援更多的個性化需求

  1. cdn自動化
  2. 更加完善的持續整合
  3. 單元測試,包括程式碼,互動測試
  4. mock資料,實現前後端真正0接觸

希望

大家在開發過程中遇到任何問題,希望可以給我們留言,我們會不斷優化專案。未來,我們還會加入mobx、rxjs、immutablejs、GraphQL等,也希望在和大家的探討中,持續進步。

專案準備

本專案基礎環境必須依賴nodejsnpm,未安裝的朋友可以去官網自行安裝,安裝教程這裡不詳細說明,安裝完成後使用如下命令,檢視是否安裝成功。

node -v
npm -v
複製程式碼

####初始化專案
本專案我們使用wci-cli腳手架初始化專案

  • 全域性安裝wci-cli
npm install -g wci-cli
複製程式碼
  • 建立專案
    wci-cli 腳手架可以建立三種專案,分別是1.純淨的react專案 2.包含antd的react專案 3.包含antd-mobile的react專案,命令如下
wci new myapp
複製程式碼

執行命令後,命令列會提示是否需要安裝antd以及選擇antd型別,即可完成專案初始化,如下

webpack工程化整合React技術棧(一)

專案目錄

myapp
├── app // 專案業務程式碼
│   ├── assets // 靜態檔案目錄(圖片、字型等)
│   ├── script // js程式碼目錄
│   │   ├── actions // redux action目錄
│   │   ├── componets // react 無狀態元件目錄
│   │   ├── containers // react 業務程式碼
│   │   ├── reducers // redux reducer目錄
│   │   ├── util // 工具包目錄
│   │   │   ├── theme.js // antd自定義樣式檔案
│   │   ├── Home.js // 首頁
│   │   ├── home.less // 首頁樣式
│   ├── styles // 全域性樣式目錄
│   ├── index.js // 專案入口檔案
│   ├── index.tpl.html // 專案html模版
├── node_modules // 依賴包目錄
├── .babelrc // babel配置檔案
├── .eslintrc // eslint程式碼校驗配置檔案
├── .gitignore
├── package.json
├── README.md
├── wci.json // wci專案配置檔案(主要配置一些開發、測試、生產環境的資訊)
└── webpack.js // webpack自定義配置檔案
複製程式碼

執行如下命令,執行開發環境

cd myapp
npm run start
複製程式碼
webpack工程化整合React技術棧(一)
webpack工程化整合React技術棧(一)

如上圖,我們的專案已經跑起來了…

  • 測試、釋出
    因我們需要保證測試程式碼和生產程式碼必須保持一致,所有在實際專案中,我們可以執行如下命令構建程式碼
npm run test // 測試環境打包
npm run dist // 生產環境打包
複製程式碼

測試程式碼

webpack工程化整合React技術棧(一)

生產程式碼

webpack工程化整合React技術棧(一)

到這裡,我們已經完成專案前期開發的所有準備工作,接下來,我們一起開始擼程式碼吧

專案結束後,我會為大家奉上兩篇彩蛋,分別是 1. 一步步搭建webpack前端構建工具並抽成npm單獨模組 2. 一步步構建自己的npm開發包並且以一個真例項子演示(開發一個命令列生成資料夾結構的小工具)

還要說一點

正式開始擼程式碼前,還要針對專案具體說明,包括專案程式碼目錄介紹,前後端分離專案需要注意哪些問題,前後端如何鑑權等…

都是幹什麼的

myapp
├── app // 專案業務程式碼
│   ├── assets // 靜態檔案目錄(圖片、字型等)
│   ├── script // js程式碼目錄
│   │   ├── actions // redux action目錄
│   │   ├── componets // react 無狀態元件目錄
│   │   ├── containers // react 業務程式碼
│   │   ├── reducers // redux reducer目錄
│   │   ├── util // 工具包目錄
│   │   │   ├── theme.js // antd自定義樣式檔案
│   │   ├── Home.js // 首頁
│   │   ├── home.less // 首頁樣式
│   ├── styles // 全域性樣式目錄
│   ├── index.js // 專案入口檔案
│   ├── index.tpl.html // 專案html模版
├── node_modules // 依賴包目錄
├── .babelrc // babel配置檔案
├── .eslintrc // eslint程式碼校驗配置檔案
├── .gitignore
├── package.json
├── README.md
├── wci.json // wci專案配置檔案(主要配置一些開發、測試、生產環境的資訊)
└── webpack.js // webpack自定義配置檔案
複製程式碼

以上是程式碼的全部目錄,下面我們根據功能依次介紹:

  • node_modules、.gitignore、package.json、README.md

node_modules: npm依賴包目錄,開發者可以不用管,只要知道我們專案裡所有的依賴都下載在這個資料夾下
.gitignore:git需要忽略的檔案
package.json:npm最主要的檔案,裡面寫滿了我們依賴包的結構和一些專案資訊
README.md:github的說明檔案

  • .babelrc、.eslintrc

.babelrc:babel配置檔案,可以配置部分自定義babel外掛(例如本專案裡antd自定義主題和javascript@語法糖就在這裡配置)
.eslintrc:eslint配置檔案,可以自定義配置eslint規則,詳細規則可以去官網eslint檢視

說明:這兩個模組本該配置在wci-build構建工具裡,但考慮到專案的靈活性,所有抽離出來放在專案根目錄

  • webpack.js

webpack.js:webpack loader個性化的配置檔案,可以自定義新增webpack loader

  • wci.json

wci.json:專案的配置檔案,可以自定義配置專案

{
  "index": "app/index.js", // 專案入口檔案
  "hostname": "127.0.0.1", // 開發環境IP地址(可以配置域名通過本地host轉發)
  "name": "wci-antd-app", // 專案名稱(顯示在瀏覽器title裡的名字)
  "libs": [ // 專案的公共包,後續可以自行新增
    "react",
    "react-dom",
    "axios",
    "classnames",
    "prop-types",
    "react-redux",
    "react-router-dom",
    "redux",
    "redux-thunk"
  ],
  "dev": { // 開發環境配置
    "port": 8031, // 開發環境埠
    "src": "app", // 開發環境監聽目錄
    "api": "", // 開發環境後端介面地址
    "module": {}, // 開發環境的模組包
    "is_eslint": false // 開發環境是否開啟eslint校驗
  },
  "test": { // 測試環境配置
    "module": {}, // 測試環境的模組包
    "api": "" // 測試環境後端介面地址
  },
  "prod": { // 生產環境配置
    "module": {}, // 生產環境的模組包
    "api": "" // 生產環境後端介面地址
  }
}
複製程式碼
  • app

專案目錄

├── app // 專案業務程式碼
│   ├── assets // 靜態檔案目錄(圖片、字型等)
│   ├── script // js程式碼目錄
│   │   ├── actions // redux action目錄
│   │   ├── componets // react 無狀態元件目錄
│   │   ├── containers // react 業務程式碼
│   │   ├── reducers // redux reducer目錄
│   │   ├── util // 工具包目錄
│   │   │   ├── theme.js // antd自定義樣式檔案
│   │   ├── Home.js // 首頁
│   │   ├── home.less // 首頁樣式
│   ├── styles // 全域性樣式目錄
│   ├── index.js // 專案入口檔案
│   ├── index.tpl.html // 專案html模版
複製程式碼

如上,因為react遵循元件化開發,故我們的業務程式碼全部寫在containers目錄下,並且模組的樣式檔案、高階元件寫在相對的模組下,如圖

webpack工程化整合React技術棧(一)

styles目錄用於存放專案全域性的樣式檔案,例如全域性樣式的變數檔案等…

其他

版本管理:

推薦使用gitflow來進行版本的管理,這裡不做詳細描述

前後端分離跨域:

一旦專案採用前後端分離,跨域是所有專案裡不可避免的問題,目前跨域的解決方案主要有三種

  1. 採用jsonp方式(只支援GET請求)
  2. 採用cors方式
  3. 採用node中介軟體方式(需要單獨部署nodejs服務)

我們這裡採用方式2

java程式碼

response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Headers","Content-Type,Content-Token,Content-User,X-Requested-With");
複製程式碼

nodejs 程式碼

res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers","Content-Type,Content-Token,Content-User,X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",` 3.2.1`)
res.header("Content-Type", "application/json;charset=utf-8");
複製程式碼

這種方式還可以自定義請求頭的認證資訊

不明白的朋友可以去看阮一峰大神的這篇文章

更新於2018-02-27

相關文章