webpack工程化集成React技術棧(一)

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

咱們要作什麼

技術棧

項目採用先後端分離的形式,後端選用Maven+SpringClould全家桶開發,前端選用webpack+react全家桶開發,先後端所有采用包管理工具徹底解決項目依賴管理的難題,版本管理採用git,先後端經過json交互,swgger管理接口文檔,接口所有遵循restful規範。因爲本文面向社區開放,故本文中不涉及公司業務層的代碼,本文所有代碼均爲最新編寫,咱們以一個旅遊管理系統的三個模塊爲你們演示項目(登錄登出、用戶模塊、景點模塊)。爲了快速開展,本文涉及的後端代碼直接採用Java的SSM框架搭建,源碼也將爲你們奉上。朋友們也可使用mock模擬接口數據。後期咱們在演示nodejs+espress時將接口代碼所有轉爲node形式。css

準備

因本文不是講解基礎,故你們在敲代碼前,還須要具有必定的前端基礎,部分以下html

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

解決什麼問題

本項目集成了最新的react1六、react-router四、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形式依賴。

還有什麼問題要解決

雖然通過大半年迭代,但咱們還須要在實際項目開發中支持更多的個性化需求vue

  1. cdn自動化
  2. 更加完善的持續集成
  3. 單元測試,包括代碼,交互測試
  4. mock數據,實現先後端真正0接觸
  5. ...

但願

你們在開發過程當中遇到任何問題,但願能夠給咱們留言,咱們會不斷優化項目。將來,咱們還會加入mobx、rxjs、immutablejs、GraphQL等,也但願在和你們的探討中,持續進步。java

項目準備

本項目基礎環境必須依賴nodejsnpm,未安裝的朋友能夠去官網自行安裝,安裝教程這裏不詳細說明,安裝完成後使用以下命令,查看是否安裝成功。node

node -v
npm -v

初始化項目

本項目咱們使用wci-cli腳手架初始化項目react

  • 全局安裝wci-cli
npm install -g wci-cli
  • 建立項目

wci-cli 腳手架能夠建立三種項目,分別是1.純淨的react項目 2.包含antd的react項目 3.包含antd-mobile的react項目,命令以下webpack

wci new myapp

執行命令後,命令行會提示是否須要安裝antd以及選擇antd類型,便可完成項目初始化,以下ios

項目目錄

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

如上圖,咱們的項目已經跑起來了...

  • 測試、發佈

因咱們須要保證測試代碼和生產代碼必須保持一致,全部在實際項目中,咱們能夠運行以下命令構建代碼

npm run test // 測試環境打包
npm run dist // 生產環境打包

測試代碼

生產代碼

到這裏,咱們已經完成項目前期開發的全部準備工做,接下來,咱們一塊兒開始擼代碼吧

項目結束後,我會爲你們奉上兩篇彩蛋,分別是 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目錄下,而且模塊的樣式文件、高階組件寫在相對的模塊下,如圖

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-26

相關文章
相關標籤/搜索