Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(三)--前后端环境配置

前言

之前都是介绍一些基础知识,在这一节,我们就要开始实战coding了。正所谓磨刀不误砍柴工,准备工作显得尤为重要。很多demo只是追求效果的实现,并不注重整个demo的架构性。从我个人的角度看来,既然是demo,就应该是有参考价值的,而作为web的demo,就更加应该凸显整个demo的结构,所以这一节着重讲解个人喜欢的node项目的前后端架构。
另,本教程乃系列教程,如需从头看起,可先看前面两篇博客:
http://www.cnblogs.com/yuanzm/p/4179766.html
http://www.cnblogs.com/yuanzm/p/4205891.html
源代码地址是:https://github.com/yuanzm/Node-Chat-Demo

后端架构之Express框架

和大多实战demo一样,我们的后端会采用Node的官方推荐框架Express。根据Express官网的定义:Express 是一个简洁而灵活的 node.js Web应用框架, 提供一系列强大特性帮助你创建各种Web应用。之所以选择框架而不是采用原生开发,主要有两个原因。其一,框架帮助我们抽象出了很多功能,能帮助我们快速搭建Web应用;其二,用Express新建的项目,本身具有非常优秀的MVC架构,能够让我们更加良好的管理我们的项目。

  • Express安装
    Express的安装非常简单,只需要采用在CMD窗口输入npm install -g express即可,其中-g代表全局安装。这个命令默认安装的就是最新版本的Express。为了验证Express是否安装成功,通常在命令行输入express -V查看版本来确认。

    如图所示,输入如上命令时出现了“‘express’不是内部或者外部命令,也不是可运行的程序或者批处理文件”提示。原来,最新express4.0版本中将命令工具分家出来了(项目地址:https://github.com/expressjs/generator),所以我们还需要安装一个命令工具,命令如下:
    npm install -g express-generator

    到这一步,我们成功安装了最新的Express,也就是v 4.11.2
  • 新建一个Express项目
    新建一个Express项目非常简单,只需要在命令行输入express project-name即可。需要注意的是,在新建Express项目的时候,需要指定前端模板引擎。根据百度百科的定义,模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。Express默认采用的模板是jade模板,我们的demo也将采用这这个模板,所以不需要手动指定。本实战教程中,我们新建一个名为Node-Chat-Demo的项目。在命令行先输入express Node-Chat-Demo,然后按照提示输入cd Node-Chat-Demo && npm install就完成了后端基础环境的搭建。下面是这一步之后的文件目录截图(其中LICENSE以后的为Git管理需要的文件,可忽略):
  • 项目简介
  1. bin是express本身配置的启动文件,我们将不采用,可忽略
  2. node_modules是后端使用的node插件
  3. public防止了前端文件
  4. routes是express的路由模块
  5. view是express的模板引擎放置的地方
  6. app.js是express项目的配置文件,也可以算是项目入口文件
  7. package.json声明声明项目中使用的模块
  • 项目启动
    Express项目的启动有自己独特的方式--npm start,但是博主尝试之后发现这个并不能监听文件变化,也就是在文件更改的时候需要重新启动项目,这在调试的时候就会显得非常麻烦。针对这种情况,我们将采用一个叫做supervisor的npm包,npm包的主页是supervisor。安装也很简单,只需要在命令行输入npm install supervisor -g全局安装即可。然后我们在app.js的33行后面加入两行:
    app.listen(3000); console.log("Listening on port 3000")

    最后只需要在项目根目录输入supervisor app.js就能够在监听文件变化模式下启动我们的项目了。


    到这里后台就已经搭建好了,接下来讲解前端架构。

前端架构之前端自动化工作流

前端给很多开发者的印象就是一堆HTML和CSS和Javascript,杂乱无章和没有难度。其实不然,正因为Web前端开发零散化的特性,使得前端架构尤为重要。什么叫零散化特性呢,这是和后台开和安卓开发等对比而来的。在安卓开发中,有强大的Eclipse,新建一个项目,整个架构完全给你搭建好了,不用自己操心。对于传统的后台开发,经常采用各种MVC框架比如我们刚刚采用的Express,一行命令同样把结构什么的全给你弄好了。但是前端就完全不一样了,因为他只是整个项目的一个组成部分,通常没有特定的结构,经常是一堆css和js在需要的时候出现,显得尤为零散。当然正是因为这种特性才让前端开发显得更加灵活和有意思,在这个实战教程中,将采用本人自己总结的一套自动化工作流,力求维持项目的有序性。这个自动化工作流主要采用了browserify、Sass、Grunt,下面逐一介绍。

  • 前端模块化之browserify

    这里特指前端模块化是因为后端的Node本身良好支持了模块化开发,前端的Javascript暂时还不支持模块化开发,或者说离模块化广泛推行的一天还有很长一段时间。为了能够在前端使用模块化的编程思想,可以采用强大的browserify。什么是browserify呢?Browserify 通过预编译的方法,让Javascript前端可以直接使用Node后端的程序。我们可以用一套代码完成前后端,不仅工作量变少了,程序重用性增强,还可以直接在浏览器中使用大量的NPM第三方开源库的功能。直观一点表达就是通过browserify,我们可以像写Node一样把每个js文件当作一个模块,实现特定的功能,最终只暴露模块接口。browserify会分析我们的模块引入顺序,形成一棵模块依赖树,最终可以只生成一个js文件。最终只生成一个js文件的好处是显而易见的,浏览器下载200k的文件和下载几k的文件所用的时间并不会差别很大,把所有文件合在一起会加快页面加载速度。从互联网结构的角度来看,这样能够大幅度减少http请求的数量,提高网站性能。对于怎么使用browserify,这里不做累赘,会在后面的教程和介绍Grunt时一并提及,这里只附上Browserify官网主页
  • CSS预处理器之Sass

    我们知道,CSS是没有语法的,所以写CSS其实是一件非常烦人的事情。很自然地,有人就开始为CSS加入编程元素,这被叫做"CSS预处理器"(css preprocessor)。它的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件。在本实战教程中,我们选择Sass。Sass是CSS的一个扩展,它使CSS的使用起来更加优雅和强大。简而言之,Sass可以理解成CSS的超集,你可以在Sass里面写熟悉的CSS。Sass的终极目标是解决CSS的缺陷。如我们所知,CSS并不是一个完美的语言。CSS虽然简单易学,却也能迅速制造严重的混淆,尤其是在工程浩大的项目中。本文同样不涉及Sass的使用教程,因为Sass非常简单,只需要好好看看文档即可。这里推荐一个教程:http://www.w3cplus.com/sassguide/
  • 使用Grunt

    之所以把Grunt放到最后面是因为整个自动化工作流的核心是基于Grunt的。我们可以使用Browserify,可以使用Sass等其他一系列的工具,但是使用它们大多数都需要用到命令行操作,如果我们每次修改文件都要手动在命令行进行编译操作将会使开发效率大大降低。自然而然的,自动化工具就会出现,目前最主流的自动化工具应该是Grunt和Gulp。什么是Grunt呢?Grunt是Javascript任务运行工具,对于Grunt的优势,Grunt官网自己给出了非常好的解答:Grunt是一个庞大的生态系统,每天都在成长。你可以自由的选择数以百计的插件以帮助你自动化的处理任务。如果你所需要的插件还被有人创建,那么你可以自己创建插件并通过npm很方便的发布以供更多人使用并一起完善。其中生态系统这四个字是非常重要的,Grunt本身很优秀,但是不算杰出,因为Grunt是基于文件的,当项目很大的时候,就会非常慢!Grunt之所以如此流行,正式因为Grunt有良好的社区支持。
  • 前端工作目录
    正如前面所述,采用Express框架的项目前端文件主要放置在public文件夹里面。我们先来看看最终的public目录:

    大概介绍一下每个文件夹的作用:
  1. .sass-cache是Sass在预处理的过程中产生的缓存文件,可忽略
  2. node_modules是前端使用的node插件,在写好Gruntfile.js文件之后在public文件夹根目录在命令行运行npm install会自动成成
  3. asserts是静态资源如图片存放的地方,里面包含一个文件夹images,存放了所用到的图片
  4. bin是Grunt处理之后的文件,包括两个文件夹,分别是jscss,包含了最终生成的main.js和main.css文件,在运行Grunt的时候会自动生成这两个文件夹,新建bin即可
  5. lib是前端使用到的类库存放的地方,包括jquery和bootstrap等,暂时先新建空的lib文件夹,后续使用到了某个类库添加即可
  6. src顾名思义是源代码存放的地方,我们在开发过程中编写的js和scss文件都存放在这里,包括两个文件夹,分别是jsscss,分别包含了开发过程中的js和scss文件
  7. Gruntfile.js是Grunt的配置文件,复制下面贴出的Gruntfile.js即可。
  8. package.json用来声明声明项目中使用的模块,复制下面贴出的package.json即可。
    使用Grunt关键是写好它的配置文件,包括package.json和Gruntfile.js两个文件。对于怎么书写这两个文件,博主推荐大家看看Grunt的官方主页,这里仅贴上本实战教程的Gruntfile.js和package.json文件。
    1) Gruntfile.js
(function() {
  module.exports = function(grunt) {
    var remapify = require('remapify');
    grunt.initConfig({
      //每次运行Grunt的时候清除之前生成的文件
      clean: {
        bin: ["bin"],
        sassCache: '.sass-cache'
      },
      //分析模块依赖树,最后生成一个main.js文件
      browserify: {
        dev: {
          expand: true,
          flatten: true,
          src: ["src/js/main.js"],
          dest: "bin/js",
          ext: ".js"
        }
      },
      //压缩js文件
      uglify: {
        build: {
          files: [
            {
              expand: true,
              cwd: 'bin/js',
              src: '**/*.js',
              dest: 'dist/js'
            }
          ]
        }
      },
      //压缩css文件
      cssmin: {
        build: {
          files: {
            "dist/css/main.css": ["bin/css/main.css"]
          }
        }
      },
      //监听文件变化,如果src文件夹中的js或css文件变化了,执行任务`browserify`和`sass`
      watch: {
        compile: {
          files: ["src/**/*.js", "src/**/*.scss"],
          tasks: ["browserify","sass"]
        }
      },
      //scss文件编译成css
      sass: {
        dist: {
          files: {
            "bin/css/main.css": "src/scss/main.scss"
          }
        }
      }
    });
    //加载上述任务所需要的插件
    grunt.loadNpmTasks("grunt-contrib-clean");
    grunt.loadNpmTasks("grunt-browserify");
    grunt.loadNpmTasks("grunt-contrib-watch");
    grunt.loadNpmTasks("grunt-contrib-sass");
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.loadNpmTasks("grunt-contrib-cssmin");
    grunt.loadNpmTasks("grunt-contrib-copy");
    //定义被执行的任务列表
    grunt.registerTask("default", function() {
      return grunt.task.run(["clean:bin","browserify", "sass", "watch"]);
    });
    return grunt.registerTask("build", function() {
      return grunt.task.run(["clean:bin", "clean:dist", "browserify", "sass", "clean:sassCache", "cssmin", "uglify", "copy"]);
    });
  };
}).call(this);

2) package.json

{
  "name": "Node-Chat-Demo",
  "version": "0.0.1",
  "author": "yuanzm",
  "license": "MIT",
  "devDependencies": {
    "grunt": "*",
    "grunt-browserify": "*",
    "grunt-contrib-clean": "*",
    "grunt-contrib-cssmin": "*",
    "grunt-contrib-uglify": "*",
    "grunt-contrib-watch": "*",
    "grunt-contrib-sass": "*"
  },
  "dependencies": {
    "browserify": "^8.1.3"
  }
}

简单描述一下这个工作流:在写前端代码的时候,为了充分利用好CSS,采用了Sass来弥补CSS本身的缺陷;为了落实模块化的编程思想,采用了browserify来使Javascript编写更加高效规范;为了能够最大化省去人工操作,采用Grunt来自动执行编译任务;为了升项目性能,最终生成的文件只有一个且经过高度压缩。
综上所述,在配置本实战教程需要的前端环境的时候,我们需要做以下几件事情:
(1). 按照public文件目录截图以及描述建立好需要的文件目录
(2). 确保Gruntfile.js正确的情况下在public根目录执行命令npm install
(3). 在public根目录执行命令grunt,如果没有报错,并且bin文件夹里面生成了相应的main.js和main.css,说明环境配置成功。
其中,运行grunt命令的效果图如下:

产生压缩文件的命令和效果如下:

到这里前端环境也配置好了。

posted on 2015-02-02 22:52 红豆依旧在 阅读(...) 评论(...) 编辑 收藏

导航