介绍一个node创建博客的教程并总结

接近一个月没写博客了,是因为实在不知道该写什么= =。。。

除了完成工作外,这段时间自学了一个教你使用node从0-1创建博客的教程,写的十分详细,教程也重构过几次了,已经相对比较完善,推荐对node感兴趣的同学去学习一下,除了node外最近也在看阮一峰老师的《ES6入门》,内容非常多,写的非常细,在这里我不会做总结,内容太多实在不知道怎么总结,如果我看完了,可能会挑一些自己觉得不清楚的地方记录下来吧~下面是2个教程的地址。

博客教程:《一起学 Node.js》彻底重写完毕
ES6入门:ECMAScript 6 入门

下面是对博客教程的一些个人总结,由于我只是暂时完成了一次,还没再次进行code review,如果有写错的地方,后续我会改正。

一、项目的设计模式远远比你良好的数据结构和代码质量重要的多

MVC结构图

上图是最终的项目完成后的目录结构,可以很明显的看到MVC的标准结构;

  1. models中分别为组件模型、文章模型、用户模型的建立与修改,都是对数据库的CRUD操作以及对函数进行封装。
  2. routes中为所有的路由控制,用于实现页面之间的交互逻辑与各个页面的业务逻辑,如登录、注册、留言、发表文章等等操作,业务路由分为5块,主页、文章页、登录、登出、注册,处理方式为直接调用model层中对应js包函数进行业务处理。
  3. views中为页面模板文件,存放可服用的页面模板,模板文件采用ejs来处理,如果有同学熟悉jade,当然你可以用jade重写~由于已经通过多次重构与设计,模板的可复用性已经十分高了,views文件夹内部分为各页面模板与可复用组件,可复用组件放于components文件夹内;
    可复用的组件包括:文章展示栏、导航栏、导航栏内设定操作、信息通知栏、文章评论栏;
    可复用的页面公共部分:头部模板、尾部模板,头部为设定与通知,尾部为导航设定js脚本;
    使用ejs或者jade模板的优点:Java SE的jsp知道吧。。。
  4. config内为配置文件,用于生产环境与开发环境的配置部署与切换,如数据库地址;
  5. lib内为数据库模型的声明与建立,包括用户模型、文章模型与评论模型;

这大概就是项目的整体架构和设计了,项目结束后,我们马后炮的来看看优点在哪

  • MVC的设计模式,实现业务逻辑、数据操作、视图的分离,在这里视图的可复用性是关键,否则你就真是jsp了,如果不分离而将业务逻辑与数据操作混合,后续维护我想别人是看不懂的了兄弟。
  • 生产环境与开发环境等公共数据的分离,项目开始前我们一定要清楚哪些数据是公共部分,如cookie与session的设定;而哪些是需要灵活切换配置的部分,如数据库地址、api、uri等配置。
  • 将数据模型的建立与业务逻辑的CRUD操作分离,这两者可以说是没有关系的,何必要放在一起增加其他维护者的时间成本呢?

以上3点就是我个人的一些劣见了,这只是我可以看到的优点,不代表没有其他优点,见仁见智了,也许水平更高后会有新的感悟吧。

二、关于教程中使用Mongodb的一点点学习总结

  1. 作者在教程中推荐使用的数据库可视化工具分别为Robomongo与Mongochef,在这里我推荐使用后者,Mongochef;为什么呢?因为Robomongo在本地数据库下是可以直接使用的,但是在你切换为MLab的线上数据库时,它要求你需要有unix内核,而windows是没有unix内核的,所以我想一般的前端应该都还在使用windows吧,这里希望大家避过这个坑,免得像我一样浪费了时间在调试上。
  2. Mongodb非关系型数据库,也就是说它不像SQL一样具有外键来以此进行关联查询等操作,所以我们推荐使用mongoosepopulate,教程中只使用了2个参数,pathmodel,其他参数也用的比较少,如果大家这里去看文档的这个api会发现说的比较生涩,经过我几次的实际操作,总结出来就是与mysql外键的使用时一样的,path是你需要引用到本次结果的外键名,model就是外键名对应键值,当然这里的model会根据你上一步的查询操作去查询,所以你自然是需要给一个两个数据模型都存在的字段去查询,如id,所以这个populate实际上就是mongoose封装的非关系型数据库的外键。
  3. 关于作者使用的Mongolass,不要多想,这就是对Mongoose进行封装后的插件,你完全可以选择不用,作者在文中也多次提及,所以Mongolass与Mongoose的操作是一致的,如果学习,那么你学习Mongoose就可以了,而作者的Mongolass优点就是在于中间件的增加,即这个apimongolass.plugin(),你可以对你的所有数据库操作进行中间件的封装,在操作数据库时,可直接像调函数一样复用,这是mongoose所没有的,作者也就是在这层上做了一点小事,而我们,完全是可以在数据库操作回调的数据结构上使用函数的,只是如果使用作者这套会更清晰而已;这里给个例子给大家

    //创建中间件addCreateAt,afterFind值数据操作返回结果为数组时,afterFindOne指返回为单个对象时
    mongolass.plugin('addCreateAt', {
      afterFind: function (results) {
        results.forEach(function (item) {
          item.create_at = moment(objectIdToTimestamp(item._id)).format('YYYY-MM-DD HH:mm');
        });
        return results;
      },
      afterFindOne: function (result) {
        if (result) {
          result.create_at = moment(objectIdToTimestamp(result._id)).format('YYYY-MM-DD HH:mm');
        }
        return result;
      }
    });
    
    module.exports = {
      // 注册一个用户
      create: function create(user) {
        return User.create(user).exec();
      },
      // 通过用户名获取用户信息
      getUserByName: function getUserByName (name) {
        return User
          .findOne({ name: name })
          .addCreateAt()
          .exec()
      }
    }
    

    这里可能有点不清晰,将就看一下就好,具体请去看教程内的使用。

  4. 关于mongoose与promise的关系,经过我的查询,最终的结论是,当对mongodb操作的类型返回为Query类型时,返回的结果是遵循promise规范的,我们可以直接result.then( () => {...}),那么有哪些操作是Query类型呢?下面给出大家mongoose文档API docs中query.js下的操作都是的。mongoose文档-query.js

  5. Mongodb不像SQL一切的数据都是自定义的,Mongdb会默认帮你生成一个_id作为单表中的唯一识别,而 _id如果不特殊声明,那么默认类型是Object,就是说它是一个对象,而键名为 _id,所以我们直接find({ _id: xxx })就可以了,并且这里要告诉大家的是ObjectId是一个12字节的字符串,前4个字节为精确到秒的时间戳,这里大家只知道这个就可以了,后面我会用到这个,这里给大家插一张生成规则图示。
    Mongodb-ObjectId生成规则

三、关于作者使用的一些中间件的用处与必要性
首先我们列出教程中所有用到过的中间件以及必要的包名,一一说明用处再进行筛选。

  • path (令你可以更简洁的书写路径,可省略不用,这个不用说明了吧)
  • express (帮助你快速创建web应用,后续中间件的依赖,必用)
  • express-session (基于express用于方便操纵session的中间件,要用)
  • connect-mongo (通常与express-session搭配使用,用处正如npm中官方所说’It could be interesting to re-use an existing connection’,主要用于将session存储于数据库中,使你得以复用现存的mongodb连接去使用数据库缓存,而减少对数据库的重复操作,降低动态网页响应时间与服务器过载,提高用户体验)
  • connect-flash (在session中添加了一个对象 req.session.flash = {},后续访问简单使用req.flash()即可访问,一个用于通知的中间件)
  • config-lite (作者自己写的插件。。。主要用于区分生产环境、测试环境、开发环境的不同配置,默认加载目录为config目录下,生产环境 => production.js, 测试环境 => test.js, 开发环境 => default.js,这里我们可以选择不用而自己去定义)
  • winston 与 express-winston (用于生成日志文件)
  • sha1 (加密所用的哈希算法,用于数字签名的加密,简单来说就是密码)
  • fs (方便文档流的操作,node中也有自身的文档操作模块,可用可不用)
  • monglass (前面说过了,作者自己写的基于mongoose的插件)
  • marked (markdown的包,因为评论与文章都支持markdown的形式,所以这个包用来将其转化对应的html)
  • objectid-to-timestamp (作者自己写的小插件,用于将ObjectId的前4个字节去除并加3个0返回时间戳= =。。。)
  • moment (日期格式化插件)

好了,终于大概列完了,其中作者自己写的包括congfig-litemonglassobjectid-to-timestamp,借用大司马的老师的话来说,我这么说你们懂的吧。。。都可以不用。

接下来开始列举个人认为的一些插件的使用上的必要性(注意是个人):

  1. moment+objectid-to-timestamp,前面已经跟大家解释过了_id取出来后的前4个字节,就是前8个字符是精确到秒的时间戳,你自己再后面+3个0不就是精确到微秒的完整时间戳了嘛,还要我说接下来怎么做吗?
  2. connect.flash,对象是在session中的,你自己存一个特定的对象来通知也可以,然后再render出模板文件的时候,后面第二个参数是返回的数据对象,你直接抛出去也可以,我这么说大家明白吧,不过这个插件本来就极小,你大可以别自己浪费力气了。
  3. fs,列举出来的时候说过了吧。
  4. marked,你不是专门写给我们这样的人用的话,你至于嘛,人家又不懂~

剩下好像没多少个包了吧,就这样吧,讲道理,该用就用,没多大,你自己封装自己写,也好不到哪去兄弟,本来就是为了快速开发,当然你自己也可以实现是前提,别搞半天,你自己都不懂就瞎用。。。

四、写到最后
最近确实有在学习一些东西,偶尔也在看《你不知道的javascript》中卷,但是确实知识比较凌乱,有很多可能工作中并不能用到,而ES6和这个博客教程我还能写出啥呢= =。。。两位作者本人都已经写的非常非常详细了(黑人脸),这篇博客教程最重要的是设计模式和思想 设计模式和思想 设计模式和思想,重要的事情要说3遍,,最后也希望大家多支持开源吧,无偿的维护不容易,如果付费就能够获取到人家长时间总结的经验,那么就值得我们付费,我也捐了10块给博客教程的作者,虽然少但也是个支持吧,也是我自身对这篇教程的肯定。

猜你喜欢

转载自blog.csdn.net/yolo0927/article/details/64126520