用node.js 搭建的博客程序心得(node.js实战读书笔记1)

学习node已经有一段时间了,之前把了不起的node.js看完了,基本算了解了一些node的基本的用法还有一些概念了,然后就开始看第二本node.js实战,第一章就是搭建一个博客程序。但是不得不吐槽一下node,发展得太块了,很多库已经和之前的用法不一样了,就要一直去百度google来查询最新的用法,其实我觉得这样并不见得是一件好事,因为不稳定,所以就不好学习,就要一直保持对于node的关注。不废话了,这篇文章就大概说一些在这章里面所学习到的一些东西,经验总结吧
1、express — 基于 Node.js 平台的 web 应用开发框架
这次的博客程序,就是基于这个框架下面做开发的,一个mvc的架构,不过这个框架的作者在04年的时候已经转投GO了.因为之前做php开发接触过yii和thinkphp,都是mvc的,所以这个还是比较好入门的,也比较好理解,这个框架是node上面最多人使用的。
安装很简单,使用npm就可以了

$ npm install -g express-generator

这个是安装express的程序(并不是项目,只有添加了这个程序以后才可以创建express项目)
然后就可以新建工程(项目)

$ express -e blog

$ cd blog && npm install

这样子一个博客工程就建立起来了,接下来就只要跑起来就可以了
可以直接在项目的根目录运行npm start或者进入bin目录直接node www都是可以的,大概看一下目录结构

这里写图片描述

app.js:启动文件,或者说入口文件
package.json:存储着工程的信息及模块依赖,当在 dependencies 中添加依赖的模块时,运行npm install,npm 会检查当前目录下的 package.json,并自动安装所有指定的模块
node_modules:存放 package.json 中安装的模块,当你在 package.json 添加依赖的模块并安装后,存放在这个文件夹下
public:存放 image、css、js 等文件
routes:存放路由文件
views:存放视图文件或者说模版文件
bin:存放可执行文件
先来看看app.js这个就是入口文件,也就是程序运行的主文件

//一开始就是引入各种模块
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

//引入两个路由
var routes = require('./routes/index');
var users = require('./routes/users');

//这个应该叫实例化这个项目吧
var app = express();

// 设置view的目录和使用的模板引擎,这里使用ejs,关于ejs,这个就是在html里面怎么来输出路由里面的变量的东西,和在html里面嵌套php代码很像
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// 项目的ico
//app.use(favicon(__dirname + '/public/favicon.ico'));

//日志记录的中间件
app.use(logger('dev'));
//解析son的中间件
app.use(bodyParser.json());
//解析url encoded请求的中间件
app.use(bodyParser.urlencoded({ extended: false }));
//解析cookie的中间件
app.use(cookieParser());
//这里是express现在唯一的内置中间件,静态文件存放的目录
app.use(express.static(path.join(__dirname, 'public')));

//这就使用路由了,其实我们是可以在app.js里面写好所有的方法,但是这样后面就不好维护,我们应该把方法单独拿出来,放在index.js里面去,这里就只用应用他
app.use('/', routes);
app.use('/users', users);

//简单来说就是404页面
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;

接下来就可以在index.js里面写各种方法了

2、调试
一般我们在修改代码以后,要先停掉之前运行的项目,然后重新开启,这个就和php有不一样,这样会很麻烦,但是我们可以通过一个模块来解决这个问题

$ npm install -g supervisor

安装 supervisor 。使用 supervisor 命令启动 app.js:

$ supervisor app.js

这样就不用每次关掉然后再开启,但是实际上,这样当代码有错的时候还是会一直重启执行,难以看清错误的提示,其实不好用。

3、中间件
什么是中间件,其实这个我也想了很久找了很多资料,后面发现简单理解为类似php里面的插件,引入了就可以实现一些功能,不需要你自己再大费周章来实现
4、页面通知flash
在php里面,我们可以使用一些alter之类的来提醒用户一些信息,在node这或者说express里面,可以使用flash功能,也是一个中间件,后面代码里面就可以使用来做提示了,例如这样的

这样在下面return的哪个跳转页面就有这个登出成功的提示
5、crypto
这个是node上面一个加密算法,因为js自带并没有md5的之类的加密算法,所以就要用到这些,内置了一些md5、sha1、sha256、sha512等算法,使用方法。

首先包含进来

crypto  = require('crypto');
var md5  = crypto.createHash('md5');
        password = md5.update(‘需要加密的字符串').digest('hex');

最后的password就是加密以后的字符串了,最后面的digest(‘hex’)的作用是以16进制的格式做输出,因为默认的是2进制的,会出现乱码,其实还有很多其他的加密方式。具体可以参考这篇文章
https://cnodejs.org/topic/504061d7fef591855112bab5

6、multer上传模块

var express = require('express')
var multer  = require('multer')
//这里是定义上传所在文件夹,这个是绝对路径,建议在前面加上dirname这些,要不就回上传到你所在服务器的根目录了
var upload = multer({ dest: 'uploads/' })

var app = express()

//第一种,这个表示你上传的只有一个文件,而且文件名字是avatar

app.post('/profile', upload.single('avatar'), function (req, res, next) {
  // req.file is the `avatar` file
  // req.body will hold the text fields, if there were any
})

//最多12同样名字为photos的文件夹,假如多了就会报错了
app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
  // req.files is array of `photos` files
  // req.body will contain the text fields, if there were any
})

//这个就是一次性定义比较多名称的文件了
var cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
  // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
  //
  // e.g.
  //  req.files['avatar'][0] -> File
  //  req.files['gallery'] -> Array
  //
  // req.body will contain the text fields, if there were any
})

但是其实上面这些都不是很好,因为都是在上传的时候还需要重新写一次文件的名字,因为上传上去到服务器的文件名称是随机生成的,还没有后缀,所以我就写了一个model来统一实现

var multer  = require('multer');
var storage = multer.diskStorage({
     //设置上传后文件路径,uploads文件夹会自动创建。
    destination: function (req, file, cb) {
        cb(null, '../public/images')
     },
    //给上传文件重命名,获取添加后缀名
    filename: function (req, file, cb) {
        var fileFormat = (file.originalname).split(".");
        cb(null, file.fieldname + '-' + Date.now() + "." + fileFormat[fileFormat.length - 1]);
    }
 });

 var multerUtil = multer({
    storage: storage
 });

 module.exports = multerUtil;

这里就是定义好了上传文件夹和上传以后文件的命名方式,使用方法如下

var muilter = require('../models/multerUtil.js');
//在这里定义好前端的几个上传文件
var upload = muilter.fields([
    {name : 'file1'} ,
    {name : 'file2'} ,
    {name : 'file3'} ,
    {name : 'file4'} ,
    {name : 'file5'}
]);

//实际调用
app.post('/upload',function(req,res,next) {
    upload(req,res,function(err){
        if (err) {
            req.flash('error','上传失败');
            return res.redirect('/upload');
        }
        req.flash('success','文件上传成功');
        res.redirect('/');
    })
});

这样的话,就使用起来比较有模块的思维

7、markdown

 这个东西其实没有太多好多的,其实就是因为我们平时保存的东西可能含有一些html的格式。但是保存到数据库然后输出出来的时候,系统可能无法识别,就要转化一下
var markdown = require('markdown').markdown;
doc.post = markdown.toHTML(doc.post);

然后在前端做输出的时候需要这样

<%- post %>

这样就可以识别到那些HTML的标签了

8、mongoose

在这个项目里面使用的数据库是mongodb,其实我也是第一次接触mongodb,大概了解了一下,就是一个介于关系型数据库(mysql)和非关系型数据库(redis)之间的一种数据库,支持的数据结构很多,也很松散,有点类似json这样子,而且查询语言很强大,node的很多项目都采用它,书里面使用的是原生的写法,例如下面

  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection('posts', function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //根据用户名、发表日期及文章名进行查询
      collection.findOne({
        "name": name,
        "time.day": day,
        "title": title
      }, function (err, doc) {
        if (err) {
          mongodb.close();
          return callback(err);
        }
      });
    });
  });

我只是要查询一个数据,又open又close太麻烦了,后面发现有这个mongoose,发现用起来很简单,就是保存的时候,需要整理好一下概念

链接我写了一个db.js

var mongoose = require('mongoose');
var Schema   = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var url      = 'mongodb://localhost/blog';
mongoose.connect(url);

var db = mongoose.connection;
db.on('error',console.error.bind(console,'连接错误:'));
db.once('open',function(callback){
  //第一次打开记录,这里可以写一些链接上以后的信息
});

module.exports = {
    db       : db ,
    Schema   : Schema ,
    mongoose : mongoose ,
};

然后使用的时候

var mongodb  = require('./db');
var Schema   = mongodb.Schema;
var db       = mongodb.db;

//这个类似我们要定义好一个数据库的字段一样,我们也需要对你操作的这个数据库进行一个初始化
var PostSchema = new Schema({
    name         : String ,
    title        : String ,
    post         : String ,
    tags         : [] ,
    comments     : [] ,
    pv           : {type:Number,default:0},
    reprint_info : {
        reprint_to : [{
            name: String,
            head: String
        }],
        reprint_from : {
            name  : String,
            title : String,
            day   : String
        }
    },
    time         : {
        date   : {type:Date , default:Date.now} ,
        year   : String ,
        month  : String ,
        day    : String ,
        minute : String ,
    },
});

//这个就实例化了这个对象了,可以使用这个Model来进行数据库的操作(不包含保存.save())

var PostModel = db.model('post',PostSchema);

//使用方法,对比上面那一段,这里简直简洁太多了
PostModel.find({}).sort('-_id').exec(function (err, rs) {
    if (err) {
        return callback(err);
    }
    callback(null,rs);
})

//但是要重点说明一下关于保存数据的方法,首先我们要对上面定义好的Model进行赋值,这里面的数据都是我在项目里面的,实际使用要实际的编写

var postEntity = new PostModel({
    name  : this.name ,
    time  : time ,
    title : this.title ,
    post  : this.post ,
    tags  : this.tags
});

//然后就save就可以了

postEntity.save(function(err , rs) {
    if (err) {
        return callback(err);
    }
    callback(null , rs[0]);
})

这只是一些基础的查询和插入,还有更新和删除distinct,等等一系列方法,还需要好好研究。官方文档
https://github.com/Automattic/mongoose

整个项目学习下来就是一个感受,node发展很快,做页面很方便,但是暂时还没有感受到异步的优势,毕竟这个项目只是一个入门的项目,了解到一些基本的操作,还有一个感受就是英文真的很重要,因为这个node在国内发展的时间还不是十分久,所以文档资料都是英文的,看起来还是很痛苦。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值