項目地址:https://github.com/Nealyang/R...javascript
本想等項目作完再連載一波系列博客,隨着開發的進行,也是的確遇到了很多坑,請教了很多人。遂想,何不一邊記錄踩坑,一邊分享收穫呢。分享固然是好的,
若是能作到集思廣益,那豈不是更美。咱們的口號是:堅定不會爛尾前端
本博客爲連載代碼博客同步更新博客,隨着項目日後開發可能會遇到前面寫的不合適的地方會再回頭修改。若有不妥~歡迎兄弟們不嗇賜教。謝謝!java
由於react中使用了react-router,也就是說前端是一個單頁面應用。因此咱們後端幾乎就能夠不去考慮前端路由的配置了。也就是說瀏覽器的url地址請求的頁面咱們是不作任何處理的。
可是假若不作忽略處理的話,固然是不實行的。由於當你刷新的時候,會報404.react
import path from 'path' import Express from 'express' import connectHistoryApiFallback from 'connect-history-api-fallback' const app = new Express(); const port = config.port; app.use('/',Express.static(path.join(__dirname,"..",'build'))); app.use('/', connectHistoryApiFallback());
connect-history-api-fallback 便可徹底處理完了前端的路由。而後Express.static就是咱們項目中須要託管的靜態資源文件。git
這樣的話,後段部分不須要怎麼關心前端頁面的路由了,而能夠集中精力去處理前端的API請求。因此這裏,我想把前端頁面服務器和處理API請求的服務器分開。也就是說,全部關係到
API請求的部分,我再另起一個服務器,在頁面服務中作一個代理,轉發到另外一個API server 上。
代碼以下:github
import httpProxy from 'http-proxy' import config from '../config/config' const app = new Express(); const port = config.port; app.use('/api',(req,res)=>{ proxy.web(req,res,{target:targetUrl}) }); const targetUrl = `http://${config.apiHost}:${config.apiPort}`; const proxy = httpProxy.createProxyServer({ target:targetUrl });
如上代碼,就能夠作到當我訪問/api的時候,HTTPProxy會將個人請求代理到targetUrl上,也就是api服務器。在API server 上咱們作一些關於數據庫的操做以及對前端傳過來數據的操做。web
import Express from 'express' import config from '../../config/config' import bodyParser from 'body-parser' import mongoose from 'mongoose' import cookieParser from 'cookie-parser' import session from 'express-session' const port = config.apiPort; const app = new Express(); app.use(bodyParser.urlencoded({extended: false})); app.use(cookieParser('express_react_cookie')); app.use(session({ secret:'express_react_cookie', resave: true, saveUninitialized:true, cookie: {maxAge: 60 * 1000 * 30}//過時時間 })); //展現頁面路由 app.use('/', require('./main')); //管理頁面路由 app.use('/admin', require('./admin')); mongoose.Promise = require('bluebird'); mongoose.connect(`mongodb://${config.dbHost}:${config.dbPort}/blog`, function (err) { if (err) { console.log(err, "數據庫鏈接失敗"); return; } console.log('數據庫鏈接成功'); app.listen(port, function (err) { if (err) { console.error('err:', err); } else { console.info(`===> api server is running at ${config.apiHost}:${config.apiPort}`) } }); });
如代碼所示,API server 咱們作了以下幾件事mongodb
關於express-session和cookie-parser這個後面關於免登錄的博客會介紹到。數據庫
express的路由很是的簡單,其實和react思想都是差很少的。就至關於對你請求路徑的一層層篩選過濾。express
好比咱們上面的
//展現頁面路由 app.use('/', require('./main')); //管理頁面路由 app.use('/admin', require('./admin'));
那麼如今讓咱們看看admin 和 main 中到底寫了些什麼
admin.js
import Express from 'express' const router = Express.Router(); import User from '../../models/user' import {responseClient,md5,MD5_SUFFIX} from '../util' router.get('/getUsers',(req,res)=>{ let skip =(req.query.pageNum-1)<0?0:(req.query.pageNum-1)*10; let responseData = { total:0, list:[] }; User.count() .then(count=>{ responseData.total = count; User.find(null,'_id username type password',{skip:skip,limit:10}) .then((result)=>{ responseData.list = result; responseClient(res,200,0,'',responseData) }) .catch(err=>{ responseClient(res); }) }); }); module.exports = router;
如上代碼,咱們使用express.Router來產生一個router對象,別迷糊,咱們徹底能夠理解爲這個router就是一個express的實例。跟前面的/a啓動app server沒有任何兩樣。一樣的監聽一個請求參數,而後回調函數。
注意這個router.get('/getUsers')真正匹配的完整請求路徑是:/api/admin/getUsers
上面代碼中的對數據庫的操做咱們能夠暫時不要理會。後續會介紹。這裏重點關注在後端路由的配置上。
關於後端的路由,也就是/api/xxx請求後面的xxx咱們該如何設計,這個因人而異。本身怎麼舒服怎麼來。固然,工做中得遵照一些團隊約束是固然,這個demo,我就隨意來了。
而後該demo的後端服務起的兩個服務。一個是前端頁面服務。一個是API服務。全部的請求統一到頁面 server 中。約束api請求的寫法。當爲/api請求發來時,咱們則經過HTTPProxy來代理到API server上。
數據庫的鏈接、/api 請求後的後端路由控制,都是在api server上完成的。
假若有哪裏說的不是很明白,或者有什麼須要與我交流,歡迎各位提issue。或者加羣聯繫我~
掃碼關注個人我的微信公衆號,直接回復,必有迴應。分享更多原創文章。點擊交流學習加我微信、qq羣。一塊兒學習,一塊兒進步
歡迎兄弟們加入:
Node.js技術交流羣:209530601
React技術棧:398240621
前端技術雜談:604953717 (新建)