做爲一個前端,或者說廣泛意義上的前端,應該是隻作前端應該作的事,涉及到後端相關的知識可能接觸很少,甚至,咱們在使用服務端渲染框架的時候也只是把它看成優化首屏渲染速度和利於SEO的一種手段,本文就逆向思惟的來擴展Next服務端渲染腳手架成一個全棧腳手架。前端
之前在沒接觸服務端渲染的時候就會總有這種思路,通常nodejs寫項目大致都是nodejs框架(通常我選擇express)+ 數據庫(通常我選擇MongoDB)+ 前端渲染模板,遠古時期會使用ejs、jade之類的渲染模板,慢慢的前端框架寫多了,就會嘗試使用react和vue這種流行的前端框架。嗯,這應該也是不少人的思路,也是按照這個思路,我之前寫了一篇Express + React + MongoDB實踐 —— 很巧,也是我在掘金寫的第一篇文章,思路是先搭建node端,而後渲染接入react前端框架~node
而後慢慢隨着知識掌握程度加深,逆向思考了一下,nodejs寫僞全棧其實也就是幾個要素,nodejs + 數據庫 + 前端頁面。其實服務端渲染框架已經具有了寫大前端項目的一些要素。咱們只須要在node端把路由api接入,而後在node 端鏈接上數據庫,一個簡單的全棧架構就完成了其實,剩下的就是按照咱們之前的書寫習慣與規範,進行業務開發,固然既然是全棧,在以往只寫前端頁面的基礎上你須要設計數據庫,書寫API等更加龐大的工做。在這裏我按照本身的理解粗略的畫一個圖吧,主要也是爲了讓你們能更簡單明白個人意思~react
文章寫的愈來愈高級了😄,開始本身作圖了。有時候我以爲寫文章還真是鞏固知識,梳理知識的一個很好的方式,推薦你們試一試,即便不寫文章也能夠寫筆記。git
這裏我解釋一下爲何我稱之爲僞全棧吧,全棧顧名思義,你確實一我的幹了全部的工做,前端頁面 + 後端API接口 + 數據庫設計。可是你其實也只是使用了node的路由以及一些特性中間件,nodejs不少高級功能並無使用以及後臺和數據庫相關的不少複雜邏輯也沒有涉及(事物、鎖等等亂七八糟的知識點)。做爲一個僞全棧,這些我確實不是很明白,因此這裏也不是探討複雜邏輯的地方,我只是給你們提供一個簡單的想法而已。github
總體擴展過程其實就真的很是簡單了,由於咱們是直接經過SSR框架進行擴展,因此徹底不須要考慮頁面渲染部分,也就是隻須要考慮Node + 數據庫
便可。咱們先來回顧一下項目總體的目錄結構:web
——————
| -- assets // ant-design global less var
| -- components // React UI component
| -- constants // constant directory
| -- ActionsTypes.js // save all action type
| -- ApiUrlForBE.js // save all apiUrl
| -- ...
| -- containers // React container component
| -- core // mehtod dirctory
| -- util.js // project method
| -- nextFetch.js // packing unfetch for easy use
| -- middlewares // middlewares
| -- client // client middlewares, deal redux action
| -- server // server middlewares, deal node event
| -- pages // Next.js routes
| -- redux
| -- actions // deal all projectaction
| -- reducers // deal all project reducer
| -- sagas // sace all project saga
| -- store.js
| -- static // save static source directory
| -- .babelrc
| -- .eslintrc
| -- .gitignore
| -- next.config.js // Next.js config file
| -- package.json
| -- server.js // server file
| -- pm2.config.js // pm2 deploy config file
| ... // other files
複製代碼
上面總體上是腳手架前端部分的架構,咱們接下來就一步步進行擴展~mongodb
首先,咱們新建/backend/routes
文件夾用來存放先後端的路由文件:數據庫
| -- backend // node backend
| -- routes // the backend routes
複製代碼
而後,咱們約定俗成一下,先後端交互的api所有是http://${host}:${port}/api/${apiName}
的形式,而後咱們在server.js註冊api接口服務也就是添加路由中間件。express
// server.js
const router = require('./backend/routes');
...
// 路由中間件
server.use('/api', router); // 添加router中間件
複製代碼
註冊成功咱們來嘗試寫一個前端調用node端的接口,就以獲取用戶列表爲例:
// apiUrlForBE.js
const apiServer = `${process.env.API_HOST}:${process.env.PORT}/api`;
// const API url
export default {
/**
* 獲取用戶列表數據
* @method GET
*/
getUserList: `${apiServer}/user/list`
};
複製代碼
以開發環境爲例,上面咱們設置了
apiServer = http://localhost:3006/api
,也就是全部的前端請求都會走到咱們的/api
路由而後返回數據。
// /backend/routes/user.js
const userData = [
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
...
]
// 獲取用戶列表
router.get('/list', (req, res) => {
const resData = {
data: userData
};
res.json(resData);
});
複製代碼
咱們啓動服務看一下:
/api
的服務端響應的數據,也就是說整個API接口請求的流程先後端經過了~
上面的接口成功了,可是咱們響應的接口是mock的數據,也就是靜態的,並非從數據庫中查到而後返回給前端的,因此能夠進一步完善 —— 鏈接數據庫。
咱們在/backend
文件夾下新建/db
文件夾,用來連接咱們的數據庫以及數據庫的相關配置操做。這裏以mongoDB爲例來進行相關配置:
| -- backend // node backend
| -- db // the directory of db
| -- config // db config directory
| -- models // mongoDB models
| -- shcemas // mongoDB schemas
| -- routes // the backend routes
複製代碼
// /config/config.js
// 數據庫地址: 'mongodb://用戶名:密碼@ip地址:端口號/數據庫';
// 通常若是沒設置用戶名和密碼直接寫IP地址就能夠,數據庫你能夠新建一個
module.exports = {
mongodb : 'mongodb://127.0.0.1:27017/db-name'
};
// /config/mogoose.js
// 建立mogoose實例,連接數據庫
const mongoose = require('mongoose');
const config = require('./config');
module.exports = () => {
mongoose.connect(config.mongodb, { useNewUrlParser: true });//鏈接mongodb數據庫
// 實例化鏈接對象
var db = mongoose.connection;
db.on('error', console.error.bind(console, '鏈接錯誤:'));
db.once('open', () => {
console.log('MongoDB鏈接成功!!');
});
return db;
};
複製代碼
上面咱們就把數據庫擴展好了,剩下的環節就是鏈接數據庫,進行增刪改查操做等等了。感興趣的小夥伴本身探索吧,若是想要更詳細的就留言把,不把這些代碼放到倉庫的緣由是那樣就不像一個腳手架了,更像一個Demo了。
上面的內容都完成以後,咱們就能夠開始全棧項目之旅了,做爲大禮包的額外贈送,既然是全棧,那麼確定有龐大的API接口要去寫,時間久了維護起來就比較麻煩,之前這些工做都是後端去作,如今全棧要一我的本身作,因此配套的再給你們介紹一個自動化API文檔生成工具 -- apidoc
,它能經過咱們在書寫代碼的時候進行簡單的註釋書寫,最後幫咱們生成可視化的api接口文檔。最後的實現效果就如圖所示:
更加詳細的使用說明,能夠見個人系列文章:邊寫邊學系列(一) —— 使用apidoc,搞定自動化文檔
我的很喜歡Next.js,因此這個系列文章寫的多一些,雖然使用的人不多,可是看成記錄仍是不錯的,最近本身也想寫點全棧的東西,正好打算使用這個擴展的腳手架來用,你們感興趣的話能夠多多提意見,不管是issue仍是star我都很歡迎~以及交流共同進步纔是最重要的。
【注】:這裏只是拋磚引玉,任何SSR框架其實都是能夠按照這個套路當全棧腳手架去用的,確實會比咱們從頭搭建要節省不少時間,並且採用本身最熟悉的前端框架作渲染模板確定在效率上也會有提高的~
帶後端的在
backend
分支,小夥伴不要找不到。