关于「Dremy 博客」所用一些技术的说明

作品2016-09-1510 篇评论 本站 HTTP

本博客实际上已经是我自己开发的第三套博客网站了,在深入学习前端及 JavaScript 技术之后,我就开始了本博客的开发。从博客的设计阶段到基本功能完成上线,共用了四个多月的时间,也算是坎坎坷坷。下面我就来介绍一下本站所用到的一些技术的说明。

概要

本博客采用前后端完全分离的架构,由 Node.js 提供后端 API,供 Web 端及 App 端(尚未开发)进行调用获取数据。前端采用 SPA 的形式,极大提升页面响应及加载速度,使用户得到好的用户体验。

Web 前端

在前端设计之时,我就想尽量使得博客简单化。这种简单体现在界面元素简洁、朴素、不杂乱,使得读者能够将重点放在博客的内容之中。但为了使得整个站点有更好的用户体验,仅靠最为原始的网站架构是不行的,页面的加载速度回严重影响到阅读体验,所以我决定使用 React 做一个 SPA(单页面应用)。

React - View 层框架

React 作为一个 view 层的框架,自然是整个应用的重点。React 的坑很多,自诩学习能力很强的我,硬是花了大半年才把 React 及其常用全家桶给基本掌握。除此之外,熟悉过后,使用 React 进行开发的便捷自然不必多说,良好的 SPA 效果使得用户体验相当不错,至少我对这一点还是很满意的。

React 也有它的不足之处,SEO。特别是针对本站这种博客性质网站,拥有一个 SEO 友好的访问方式是非常重要的。但 React 必须由 JavaScript 引擎执行渲染之后才能在 DOM 中将数据显示出来,所以只靠最基本的那些方式是不可靠的。想象一下,如果一个博客网站的文章写得再好,但搜索引擎连一篇文章都不能收录,想要让读者看到只能采用链接分享的方式,这样有价值吗?

但好在,React 同时也提供了服务端渲染的方案,能够完全解决 SEO 不友好的问题,但实现起来其实还是挺复杂的。为此我专门写了一篇文章来介绍 React 服务端渲染的实现 《React 客户端 / 服务端同构应用开发》,具体细节这里就不多少了。除了能够实现对 SEO 友好之外,还一点也很重要,就是首屏加载时间也能够显著减少。因为其 CSS 及 DOM 会先于 JS 文件加载,而且前两者的大小一般都不大,所以用户可以很轻易的体验到由其带来的好处。

Nginx - 前端页面缓存

刚才说到,React 可以在服务器端进行渲染操作,实际上服务器并不擅长于这样的操作,因而会使得响应时间较长,达到几十毫秒级的时间。并且由于博客作为一个读取数远大于修改数的应用,非常适合使用缓存,而且由于是 SPA 应用,所以对缓存的有效性要求也不高。考虑到这一点,我直接使用 Nginx 的 proxy_cache 作为缓存,为了简单考虑,不手动使缓存失效,直至其过期即可。这样一来,服务端的压力能大大减少,响应时间能得到提高。

Redux - 数据流控制

React 的单向数据流传递方式让很多刚接触的人迷惑,特别是在组件多层嵌套之后,把数据一层层地传下去会有很多 bug 出现,同时也让代码变得不可维护。

Redux 很好的解决了这个问题,它是 Flux 架构的一种实现,遵循 React 的单项数据流模型,使得数据的传递变得方便很多。

Webpack - 项目构建及打包

一个 React 网站项目一般会有很多 js 文件组成,每个文件负责一个功能的实现。但是在网站上线发布的时候,必须要把那些小文件全部打包,然后经过压缩等操作后才能发布。而且为了能够提升那些静态文件的加载速度,一般也会把 js、css 等静态资源文件放到 CDN 上。这个过程就叫做项目的构建。

在之前,比较流行的项目构建工具有 grunt 及 gulp,都能提供比较全面的项目构建功能。但是 Webpack 有个最大的好处,它能把一个站点所需要用到的所有静态资源文件(包括图片及字体等资源)全部打包到一个 js 文件里面。同时,Webpack 提供了很多的插件,能完成所有与项目构建相关的操作,甚至在项目开发过程中也能够提升开发效率。webpack-dev-server 配合 Webpack-hot-plugin 就是一个例子,它能够与 React 无缝集成,在修改代码后甚至不需要刷新页面,就能在无意之间替换修改的元素,极大地提升了开发效率。

CSSModule - CSS 模块化

CSS(Cascading Style Sheets,层叠样式表)的特性就是能够通过样式的覆盖来简化代码,这在传统的项目中还是很方便的。但在类似于 React 的模块化开发下,CSS 的这项特性反倒变成了一项缺点。

例如,有一个列表组件 List1,如果想给它的每一个 <li> 标签加上一个叫 list 的 class,那么在整个应用中的其它组件就不应该使用 list 作为 class 名,否则两者的样式将会相互影响。这对于开发一个小型应用的单个开发者来说可能不存在什么问题,但当开发由多人合作的大项目的时候,一个开发者负责一些组件,完全不知道其它开发者对 class 起了什么名字,非常容易导致意外的冲突,导致整个项目集成之后出现问题。并且还有一点,有时候给一个 class 取个合适的名字是相当纠结的,想了半天也不知道到底取什么名字好。

CSSModule 正好解决了这样的问题,和 Node.js 的一个文件一个 module 的机制一样,所有的 class 的作用域只在于文件内部,通过 require 结合 webpack 就能够实现加载时对 class 名称的替换。class 名称可以通过配置文件进行配置,从而能够确保整个项目中没有重复的 class 名称造成意料之外的干扰。

可以看到,本站的所有 class 名称都经过 [hash:base64:5] 参数替换,无法看到原 class 名称,所以在开发时就完全不用纠结到底给 class 取什么名字好,觉得怎么舒服就怎么来,就算取汉语拼音也不怕被别人笑话,因为别人根本就不知道(翻看源代码除外)。

Sass - CSS 预处理

Sass 这个非常实用的工具我就不多说了,它所提供的异常方便的嵌套格式是懒癌患者的福音。虽然由于 CSS 模块化导致了它的作用小了很多,但依然非常的实用。

Node.js 后端 API

项目的后端采用 Express + MongoDB + Redis 实现,提供完全 RESTful 风格的 API,权限验证使用 JSON Web Token。此 API 可供 Web 网站、管理系统及 App 客户端使用。

Express - 应用服务器

Express 作为 Node 平台上最火爆的应用服务器模块,能够自定义各种类型的中间件是它最大的特色,通过自定义许多中间件能够很好的简化代码。如使用 JWT 进行权限验证,只需要在路由之前加入与 JWT 验证相关的中间件即可完成权限的验证。同时,其对 RESTful 风格 API 支持良好,可以很方便的进行 RESTful API 的开发。

MongoDB - 数据库

在 NoSQL 数据库日渐火爆的今天,MongoDB 便是这类数据库的代表。文档型存储使得无需先设计表结构就能存取数据,以及能够直接返回嵌套的字段。对于简单的项目来说,并不需要像关系型数据库那般遵循严格的范式,更多的通过内嵌文档的形式可以满足许多需求。

其在插入文档时能够自动生成全局唯一的 UUID,从根本上支持数据库的集群分片,在大数据的处理方面有极大的优势。

Redis - 缓存及消息队列

Redis 作为内存型 KV 数据库的代表,其超快的存取速率非常适合作为缓存及消息队列的存储。考虑到 API 可能的大并发请求,迅速的数据读取是非常重要的。由于从 MongoDB 中读取的文档都是序列化的 JSON 字符串,所以可以很容易的存入 Redis 作为缓存,并能够迅速读取,可以显著减少 API 的响应时间。所以说在 API 应用中,在应用与数据库间加入一层缓存是相当重要的。

Nodemailer - 邮件发送服务

本博客加入了邮件发送功能,可以针对用户评论时留下的邮箱地址信息,当有其它用户回复的时候就会自动发送包含评论及回复内容的邮件,让用户不会错过任何信息。而对于博主来说,也能够在第一时间接收到用户的评论,第一时间就能够进行回复。这真是一项非常贴心实用的功能。

其它

为了保障所有用户的隐私信息,本博客使用了全站 HTTPS 加密。在运营商广告越来越密集的今天,全站 HTTPS 能够彻底杜绝这种野蛮的入侵方式,保护用户隐私。

同时为了优化网站的加载速度,本站所有的静态资源文件及图片文件均存放于七牛 CDN 中,这些 CDN 均使用了 HTTPS 进行加密。

总结

本站在开发的时候尽可能的使用了较为前沿但成熟的技术,通过运用这些技术,使得博客网站不仅有着不错的性能,对用户来说也有着不错的用户体验。同时,这也能体现出我建站时在这方面的技术水平。

但我知道现在的网站架构依然还有很多值得优化的地方。下一步,我准备将整个站点 Docker 化,使其能够在未来的云计算大环境下轻松部署。

本站于 GitHub 开源,如果对本站的一些技术有兴趣的话,欢迎留言讨论。

评论区

发表评论
用户名
(必填)
电子邮箱
(必填)
个人网站
(选填)
评论内容
Copyright © 2017 dremy.cn
皖ICP备16015002号