如何设计一个基于Node.js和Express的网站架构

JavaScript011

如何设计一个基于Node.js和Express的网站架构,第1张

今年七月份,我和几个小伙伴们合伙建立了一个开发团队。业务开展如火如荼的同时,团队宣传就提上了日程,所以迫切需要搭建公司网站出来。确

定目标后我们就开始考虑如果构建一个企业网站。先是进行业内调查,看了看别人家的网站是怎么做的。总体来讲,国外网站的设计和使用的技术总能比国内高很大

一截,国内很多公司,甚至是很多软件公司都不注重公司网站的构建,网站千篇一律,没有特色。很多网站都是使用Wordpress,然后自定义皮肤。也有一

些设计类公司,网站页面做的很漂亮,设计也前卫,但是前端源代码写的一塌糊涂。我们起初的方案也是想使用Wordpress作为基础来设计网站,网站UI

从已有开源的皮肤基础上修改。这样既能节省开发成本,又能体现独一无二。其实,刚开始也是这么做的,并且已经做出来了第一版了。只是实在是觉得和别人家的

网站差别不大,太普通了,并且网站也没有任何体现我们专注于Web开发这一特质。权衡再三之后,决定从头开发一个企业网站出来,使用我们团队擅长的技术重

新开发一个网站出来。决定前端使用AngularJS和Bootstrap构建,后端使用node.js和Express构建。经过一个多月的努力完成的项目的第一版。下面将详细介绍这个项目的基础结构设计。

项目整体设计

技术上,项目前端使用AngularJS和Bootstrap,后端使用node.js和Express。网站自动化构建工具使用grunt。网站整体应用了流行扁平化设计和响应式设计。当然,UI设计是我们团队的弱项,所以很多都是借鉴(抄袭)了别人的设计。网站前端代码基于HTML5,支持Chrome、Safari、Firefox及IE9+,使用IE8浏览器打开网站会自动跳转到引导用户下载现代浏览器的页面中。网站应用了响应式设计,所以在智能手机上也可以愉快地浏览。

项目是完全开源的,github上的地址是:eRealm,项目演示地址:eRealm Info &Tech。

代码结构介绍

推荐使用Webstorm打开项目。打开项目后,代码结构如下图所示:

在主体结构中从上到下介绍。app文件夹包含了所有后端代码;build文件夹中包含了最新数据库备份;config包含有网站整体的配置;logs文件夹包含网站后端记录的日志文件;node_modules是包含所有的node.js依赖包(源代码中初始没有此文件夹,运行npm install命令后所有加载的依赖包放置在此文件夹中);public文件夹包含了所有的前端代码,包括JavaScript、less、图片、Webfont等;.bowerrc中定义了bower管理前端库的下载地址;bower.json则配置了项目需要的前端库;.jshintre-client和.jshintrc-server分别为前后端JavaScript代码规范检查规则;.travis.yml为[travis](https://travis-ci.org/)自动编译配置;app.js为node.js启动脚本文件;build.sh为单独编写的自动发布bash命令;gruntfile.js为grunt配置文件;newrelic.js为newrelic的配置文件,用于监控网站性能;package.json包含了所有node.js依赖包配置。

项目后端结构

项目后端代码架构如下图所示:

主要分为两大部分:app和config。app里面按照职责不同来分类,每个脚本文件对应于不同的模块;api文件夹包含了所有api对应的业务逻辑代码,helper放置一些公用方法,如邮件发送、日志记录、数据库连接等等;templates放置的是静态邮件模板;views是后端页面模板,使用了handlebar模板引擎,其中http中放置系统错误显示页面,layouts放置模板页;routes是express对应的路由配置,所有的页面和API的路由配置都在这个文件中。config文件夹中为系统配置,按照不同环境分为开发和现场两个环境配置,all.js放置共通配置,development.js放置开发环境对应配置而production.js放置线上环境配置。配置内容包括邮件发送、数据库连接及一些第三方API所需的key等等。

项目前端结构

项目前端代码结构如下所示:

前端代码全部放置于public文件夹下。data目录包含一些静态json格式数据,后期可能会考虑放到数据库中。helper中是浏览器下载引导页面;images包含了所有项目中用到的图片,我们尽量使用第三方的图片服务器保存图片,一些小图标也尽量使用webfont。JavaScripts文件夹包含所有JavaScript文件,其中app子目录放置业务代码,业务代码都是按照业务不同封装成了不同的angularjs?controller;debug子目录放置调试用代码,而libs方式前端JavaScript库,项目中使用得JavaScript库有angularjs、jQuery及一些插件;clients.js是所有ajax请求函数;erealm.js是angularjs的主模块;language.js包含了所有多语言配置,目前支持中英文。stylesheets包含了所有的css样式及webfont,除了第三方库之外,自定义的样式全部使用了less。作为一种惯例,项目中添加了humans.txt文件,表明项目的作者信息。有关humans.txt,可以参考官方网站humans.txt。

自动化构建工具

项目自动化构建使用grunt。grunt的使用涉及开发、调试、发布阶段。开发阶段使用了图片压缩和前端代码格式美化,使用的工具是imagemin和jsbeautifier,运行grunt prepare命令。调试阶段使用了代码规范检查、less编译、自动添加浏览器前缀、自动加载运行nodejs并打开浏览器、实时监控代码变化并刷新页面等。开发中,使用grunt命令即可,为默认grunt命令。发布阶段包含了JavaScript及css合并压缩,并在文件路径上添加哈希值来避免浏览器缓存问题,同时删除开发环境中使用的代码,使用grunt build命令即可把代码切换为发布环境。

具体的使用grunt方法及相关工具的介绍,后期会有专门的技术文章讲解,这里不会详细设计技术细节。

后期持续的改进点

项目完成的比较仓促,但是我们尽量保持代码的整洁和可维护性,一些编码方式也借鉴当前流行的最佳实践。但理想是美好的,现实总是不会做到那么完美,需要不断的完善。目前存在的问题是后端代码结构不够清晰、整体代码中无用代码还没有来得及移除。框架上期望把jQuery去掉,只使用Angularjs,目前只做到了尽量不用jQuery中的方法。小图标的使用上Bootstrap和?Font Awesome重复,后期会逐步删除Font Awesome而只使用Bootstrap中带的小图标。目前,最大的问题是项目没有完整的自动化测试,这个后期会逐步添加。

总结

以上是这个开源项目的整体技术结构介绍。在这个项目中,我们会持续使用最流行的Web技术,希望得到大家的持续关注,如果有开发者能一块贡献一些代

码,我们将会非常高兴。我们已经在github.io上构建了一个技术平台来发布Web技术文章,网址是blog.erealm.cn。博客网址也同样开

源,使用了Jekyll构建。Jekyll非常强大,最大的特点是使用markdown格式来发布文章。博客的代码在这里:github。

我们做这个开源的项目的目的有两个,其一是通过这个项目来展示我们做Web项目的实力,及培养团队技术水平。其二是借助这个项目,能和同行们有个技

术上的互动和交流。如果我们的项目能让一些新手们学到一些做Web项目的经验,我们就很知足了。技术是不断革新的,而国内Web技术向来是落后于国外好几

年,这个是不争的事实。我们erealm团队乐意为国内Web贡献自己的力量,也欢迎国内同行们和我们交流Web开发经验。

获取Node安装包,可以访问以下Node.js框架官方网址:

在该页面中,我们可以看到适用于不同操作系统的、各个版本的Node安装包源文件,选中我们需要的版本类型直接下载就可以了。

2

在Windows操作系统环境下安装Node.js框架,直接运行下载好的Node安装包      源文件即可,目的路径一般选择如下:

D:/nodejs/

3

安装完毕后,读者可以到该目录下浏览一下具体内容,这样会对Node环境有一个大致的了解。

方法/步骤2

在Ubuntu(Linux)环境下需要运行apt命令进行安装,具体方法如下:

sudo apt-get install nodejs

如果想获取最新的Node安装源,具体方法如下:

sudo add-apt-repository ppa:chris-lea/node.js

sudo apt-get update

sudo apt-get install nodejs

3

一般情况下,node命令会被自动安装在以下路径之中(视不同的Ubuntu系统版本而定):

/usr/local/bin/node

END

方法/步骤3

1

大致经过以上这几步的操作,Node.js框架就安装完毕了,为了检验Node环境是否正确,可以使用以下命令检测Node的版本:

node -v

2

如果显示出正确的版本号,则说明Node环境搭建成功了。

如果想要更好地学习nodejs,可以练练代码段的相关图书。

Node.js非常适用于Web开发,但是现在无论是一个网站,还是Web App都已经成为包括很多不同部分,如前端、数据库、业务模块、功能模块等等的大型项目,使用Node.js从零开始进行Web开发,也许大中型团队能够 胜任,但对于个人和小型团队来说是不现实的。这时候框架就成为Web开发利器,对于个人开发来说几乎是必不可少。那么如何选择Node.js Web开发框架呢?

首先,我们必须要弄清楚的是,我们需要的是——

程序 or 框架?

程序是已经成型的应用,你需要的是为它搭建环境、添加配置,然后就可以运行起来;框架则是应用的骨架,你需要为它添加数据模型、业务逻辑,它才能成为应用,开始提供服务。

事实上,对于Web开发来说,程序和框架的区别正越来越模糊,比如几乎妇孺皆知的Wordpress,它是一个博客程序,但它丰富的插件以及高度的 自定义能够支持很大程度上的二次开发,在这点上它比起一些PHP框架也并不逊色。我个人认为,如果重心在于提供服务而不是掌握技术,有WordPress 这样的程序是没有必要使用框架的。

可惜的是,由于Nodejs还很年轻,目前还没有WordPress这样的程序,因此目前在Node.js开发里,如果想做出自己想要的作品,框架是必然的选择。如果是某些特定类型的应用,可以尝试一些开源的程序,比如要用Nodejs做博客,有Hexo、Ghost等。

Node.js Web框架有哪些?

Node.js里的Web框架分为API框架和Web应用框架。前者能够开发出RESTful的API,后者也能开发出RESTful API,但还包括模板、渲染等为前端所准备的功能。

API框架的使用场景是为跨平台应用提供统一的数据模型,而渲染由前端/客户端自行解决。目前比较知名的API框架有

restify(文档、Github、NPM)

ActionHero.js(官网、Github、NPM)

LoopBack(官网、Github、NPM)

Frisby(官网、Github、NPM)

Fortune.js(官网、Github、NPM)

Web应用框架顾名思义,就是为了打造Web应用所开发的框架。这里有两种风格的Web应用框架。

一个是Sinatra风格,另一个是Rails风格。Sinatra和Rails都是Ruby语言的Web框架,后者的影响力更大也更为知名。这里简单的解释一下两种风格是什么意思。

Sinatra风格是指高度可配置,注重开发的自由度。代表性的Nodejs Web框架有:

Express(官网、Github、NPM)TJ大神开发,Node.js官方推荐

hapi(官网、Github、NPM)

koa.js(官网、Github、NPM)

flaliron(官网、Github、NPM)

total.js(官网、Github、NPM)

locomotive(官网、Github、NPM)

Rails风格则是指不重复自己和约定优于配置,以及严格遵循MVC结构开发。代表性的框架有:

Sails.js(官网、Github、NPM)

geddy(官网、Github、NPM)

CompoundJS(官网、Github、NPM) 原railswayjs

这两种风格无所谓谁优谁劣,全凭使用者的偏好。

而在这两种Web框架之外,还有更大型的框架,即全栈框架,其中的代表是MEAN。

MEAN?

MEAN指MongoDB+Express+Angular.js+Node.js,这一组合包括运行环境、数据库、Web框架和前端引擎。被称为 全栈框架(Full-stack framework)。这其中除了Node.js之外,每一个都是可替换的,目标是创建从前端到后端,全部使用javascript的Web应用。

由于这一框架的完善性,有人将其称为LAMP的接班人。LAMP即PHP的典型运行环境,Linux+Apache+MySql+PHP,被大量的用于各种虚拟主机上。

MEAN看似庞大,但事实上要构建完整的现代化Web应用,特别是SPA(单页面应用),这几个组件都是难以缺少的,并且,其中每一项几乎都是目前 情况下的最佳选择,因此用于学习和重头开始打造新的Web应用是非常合适的。但由于实际业务的独特性,很可能要替换其中的组件,比如用Mysql来替换 MongoDB,因此,学习其中的原理和架构,打造自己的类MEAN框架也是一种选择。

作为个人和小团队来说,全栈框架MEAN基本上足够了,但目前大多数全栈框架还包含一项特性,那就是实时,拥有实时功能的框架我们又称为实时框架。

实时框架好吗?

实时框架(Real-time framework)指包含了webSocket的双向通信功能,能够在服务器和客户端做到实时通信的框架。

服务端和客户端自由通信的需求一直都在,但由于HTTP协议本身的局限性,因此催生了Comet等变通的方法,但即使这样也离实时相距甚远。而当 Node.js兴起后,另一个HTML5技术webSocket也渐渐成熟,人们突然发现,实时通信一下子变得触手可及,于是webSocket技术在 Node.js中得到大量的应用,其中最为知名的模块就是socket.io,而各种全栈框架也纷纷加入实时特性来应对更广阔的开发需求。

目前有代表性的实时框架有:

Meteor(官网、Github、NPM)

MEAN.io(官网、Github、NPM)

Derby(官网、Github、NPM)

SocketStream(官网、Github、NPM)

不过说实话,目前能看到的实时通信的应用场景其实不多,其中大多集中于聊天室、to-do、实时图表、在线游戏等领域。其他领域使用实时特性不但没必要,而且是对服务器资源的浪费。因此目前是否要采用实时框架,要看具体的项目而定。

以上基本就是Node.js Web框架的现状了,相信看到这里,对于选择何种框架读者已经心里有数了吧。最后再介绍一个容易搞混的概念,和解释一下我的选择。

YEOMAN?

第一次见到这个词,我还以为它和MEAN有什么联系。事实上,它们是截然不同的两个东西。YEOMAN由YO(脚手架)、grunt(构建工具)、bower(包管理器),它代表的是一种工作流,与框架开发的思维方式完全不同。具体的介绍可见这里。

YEOMAN能够和框架达到类似的目的,都是为构建一个Web应用做好准备,但是要不要采用YEOMAN,则是见仁见智。我个人的看法是,学习 YEOMAN本身就需要不少时间,并且有一定的学习门槛。至少在目前,使用框架开发还是相对经济的,而如果以后YEOMAN这种模式推广开来,再来学习也 不迟,更何况有一定的Node.js项目经验之后再来学习YEOMAN要轻松很多。

事实上,我还是很认可YEOMAN这种Generator+package Manager的模式的,这是因为Node.js本身崇尚微模块的 概念,即无论是多么小的功能,都将它们模块化,甚至大的模块也要拆分成小的模块,然后通过搭积木的方式来构建应用。这样能够彻底的解耦,对于不容易调试的 Javascript来说,也有助于定位和修复应用中的问题。Generator就是这种理念催生下的产物,通过选择不同的配置和选项,将积木搭起来。不 过对于这种模式目前大家也还处于实验当中,不急于进行实际应用。