从前端到后台:一个聊天项目带你撸全栈

  • Kevin
  • 8 Minutes
  • 2017年5月28日

差不多花了整整两个星期,终于把这个聊天APP的后台架构搭建出来了。虽然花的时间比较多,但这也是我第一次写后台,其实也并没有想象中的那么难,但也还是很折腾,尤其是在数据库这一块,几乎全部都是英文文档(看得都只想**)。

项目概述

该聊天App高仿iOS端的微信,当然没这么复杂,目前已实现功能有:

现在几乎每天都在更新,争取把它做得更像一个正规的聊天应用。不过由于该应用是基于Web页面的,用户体验和数据持久化等诸多方面肯定没法跟客户端应用相比。

前端Web界面

前端界面在一个多月前就已经差不多写出来了,苦于一直没有后台接口(API)的支持,所以仅仅只是一个界面展示,并无实际聊天的功能。

对前端我就不做深入的介绍了,主要是基于Vue来实现的。而且对于一个前端开发者来说,后台实现可能更具有挑战性。

后台实现

为了实现真实的聊天功能,我决定自己来搭建后台,这也是我第一次写后台。整个后台应用基于Node.js平台,采用express模块来搭建HTTP服务器,聊天功能采用WebSocket实现,数据库使用的是MongoDB

主要使用的技术栈包括:Node.jsexpressexpress-sessionexpress-wsmongodbmongoose

后台逻辑分析

初次写后台,最难的可能就是架构了,因为你要对整个应用的需求、实现的功能、数据的模型等有一个清晰的思路逻辑。我可能也就是在这方面花的时间是最多的,总是不知道该如何下手。很多次都是写着写着就写不下去了,因为逻辑行不通了。

遇到的问题和难点

其实问题还有很多很多,这可能对于后台开发人员来说都显得小儿科,但这些真是我开发过程中遇到的问题,当然还不止如此。到目前为止,有的问题已经解决了,有的问题仍未解决,或没有找到更好的解决方案。

其实,学习也就是一个发现问题,然后解决问题的过程。当你把一个一个的问题都解决之后,你也就在不知不觉中慢慢成长起来了。贵在坚持,也难在坚持。

模块介绍

对于上面的问题,我也是自己网上找资料,目前主要引用到了这些模块框架:

主目录结构

由于是第一次写后台,后台结构分的并不是很清晰。

主要的架构就是这样,基本操作都在routes目录下,因为后台也就是为前端写接口。在routes目录下又分了不同的子路由,比如:frienduserwsmessage等,分别处理不同的请求。

看起来很简单,但做起来真的不容易,最可怕的是代码量大了,你会陷入一个大量重复代码和无限回调的噩梦,我想大部分人都经历过js的回调噩梦。目前也只是有了个初步的逻辑架构,后面可能会根据需求的不同而变更。代码也需要优化,有的自己一遍一遍写起来就恶心。

两个容易误会的概念

本篇文章主要作个整体的介绍,因为该Web应用目前仍在开发中,很多功能还不确定,等后面整个逻辑清晰了再作总结。下面说两个很经典的问题,也是前端很容易误会的问题,至少我是误会了很久。

跨域

在这之前,对跨域访问是一知半解,不知道到底该如何解决这个问题。这里要提出,跨域访问不是前端的问题,其实大部分都是后台的问题。对于跨域,网上有两种解决方案:JSONP和Ajax。对于JSONP没什么研究,不作介绍,好像也并不是很实用,这里主要介绍Ajax跨域的问题。

下面是我后台解决跨域问题的方案:

1
2
3
4
5
6
7
8
9
10
app.use((req, res, next) => {
res.set({
// 跨域cookie 不能为通配符 *
'Access-Control-Allow-Origin': 'http://localhost:8808',
'Access-Control-Allow-Methods': 'GET,POST',
// 跨域cookie必须为true
'Access-Control-Allow-Credentials': true
});
next();
});

简单的说一下,跨域其实浏览器是可以正常的收到来自于服务的响应,只是无法正确的解析。通过在服务器端对响应头写入'Access-Control-Allow-Origin': '*''Access-Control-Allow-Methods': 'GET,POST',浏览器才能正确的解析服务器的响应。记住是在服务器端对响应头的操作,我之前一直误会是在前端的请求头中写入,现在想想有点傻逼了。

对于'Access-Control-Allow-Credentials': true,是用来处理跨域中cookie的问题。因为默认情况下,cookie是不允许在跨域访问中传输的。要解决这个问题,Access-Control-Allow-Origin的值就不能为通配符*,并且前端通过Ajax发起请求时也要做处理。

1
2
3
4
5
6
7
$.ajax(url, {
method: 'GET',
xhrFields: {
withCredentials: true
},
...
})

之前对Cookie的认识一直就是一种类似于缓存的东西,但具体是做什么,怎么用,并不清楚。这是要指出两点:

那么,这下就清晰多了。如果你仅仅只是搞前端,基本上是用不到Cookie的。虽然也可以通过js代码读取到cookie数据,但大部分服务器都是禁用掉此操作,也就是让你在前端无法通过js代码读取到cookie的内容,读取到的是空字符串。

因为cookie是每次发起请求都会自动携带的,所以服务器就可以通过cookie来识别用户的身份、是否处于登录状态等,就像你进入某个网站有时候会自动识别你的身份并登录。而cookie也是可以设置过期时间的,所以服务器端就可以控制你的身份多久失效,失效之后你就要重新登录了。

你可以自己尝试在浏览器的控制台通过document.cookie来获取一下网站的cookie信息。也可以尝试清除浏览器的cookie,然后再刷新你登录的网站,看是否需要重新登录。

我这个项目中用到的express-session就是通过cookie来识别用户身份的。使用express-session的好处就是你不需要自己要操作cookie,使用起来简单。

后记

我一般写文章都是针对自己实际遇到的问题来的,我目前也是在不断的学习中,过几天就会写一篇文章作个总结。