做为一个前端,或者说广泛意义上的前端,应该是只作前端应该作的事,涉及到后端相关的知识可能接触很少,甚至,咱们在使用服务端渲染框架的时候也只是把它看成优化首屏渲染速度和利于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
分支,小伙伴不要找不到。