express 初建项目注意事项

一、概述

1、新建一个项目目录

  > mkdir hello-world

2、进入该目录,新建一个package.json文件,内容如下。

  //代码定义了项目的名称、描述、版本

{
  "name": "hello-world",
  "description": "hello world test app",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "4.x"
  }
}

3、安装(modules)

  > npm install

4、新建一个启动文件ndex.js文件

var express = require('express');
var app = express();

app.use(express.static(__dirname + '/public'));

app.listen(8080);

5、例子:

// routes/index.js

module.exports = function (app) {
  app.get('/', function (req, res) {
    res.send('Hello world');
  });
  app.get('/customer', function(req, res){
    res.send('customer page');
  });
  app.get('/admin', function(req, res){
    res.send('admin page');
  });
};
// index.js
var express = require('express');
var app = express();
var routes = require('./routes')(app);
app.listen(3000);

二、运行原理

1、底层:http模块

 

  http模块生成服务器的原始代码如下: 

var http = require("http");

var app = http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end("Hello world!");
});

app.listen(3000, "localhost");

上面代码的关键是http模块的createServer方法,表示生成一个HTTP服务器实例。该方法接受一个回调函数,该回调函数的参数,分别为代表HTTP请求和HTTP回应的request对象和response对象。

Express框架的核心是对http模块的再包装。上面的代码用Express改写如下:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello world!');
});

app.listen(3000);

 比较两段代码,可以看到它们非常接近。原来是用http.createServer方法新建一个app实例,现在则是用Express的构造方法,生成一个Epress实例。两者的回调函数都是相同的。Express框架等于在http模块之上,加了一个中间层。

2、什么是中间件

简单说,中间件(middleware)就是处理HTTP请求的函数。它最大的特点就是,一个中间件处理完,再传递给下一个中间件。App实例在运行过程中,会调用一系列的中间件。

每个中间件可以从App实例,接收三个参数,依次为request对象(代表HTTP请求)、response对象(代表HTTP回应),next回调函数(代表下一个中间件)。每个中间件都可以对HTTP请求(request对象)进行加工,并且决定是否调用next方法,将request对象再传给下一个中间件。

一个不进行任何操作、只传递request对象的中间件,就是下面这样。

function uselessMiddleware(req, res, next) {
  next();
}

 上面代码的next就是下一个中间件。如果它带有参数,则代表抛出一个错误,参数为错误文本。

function uselessMiddleware(req, res, next) {
  next('出错了!');
}

 △抛出错误以后,后面的中间件将不再执行,直到发现一个错误处理函数为止。

3、use方法

  use是express注册中间件的方法,它返回一个函数。下面是一个连续调用两个中间件的例子

var express = require("express");
var http = require("http");

var app = express();

app.use(function(request, response, next) {
  console.log("In comes a " + request.method + " to " + request.url);
  next();
});

app.use(function(request, response) {
  response.writeHead(200, { "Content-Type": "text/plain" });
  response.end("Hello world!\n");
});

http.createServer(app).listen(1337);

上面代码使用app.use方法,注册了两个中间件。收到HTTP请求后,先调用第一个中间件,在控制台输出一行信息,然后通过next方法,将执行权传给第二个中间件,输出HTTP回应。由于第二个中间件没有调用next方法,所以request对象就不再向后传递了

就是将第一个中间件的requet传递给第二个中间件。

use方法内部可以对访问路径进行判断,据此就能实现简单的路由,根据不同的请求网址,返回不同的网页内容。

var express = require("express");
var http = require("http");

var app = express();

app.use(function(request, response, next) {
  if (request.url == "/") {
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.end("Welcome to the homepage!\n");
  } else {
    next();
  }
});

app.use(function(request, response, next) {
  if (request.url == "/about") {
    response.writeHead(200, { "Content-Type": "text/plain" });
  } else {
    next();
  }
});

app.use(function(request, response) {
  response.writeHead(404, { "Content-Type": "text/plain" });
  response.end("404 error!\n");
});

http.createServer(app).listen(1337);

 

 

三、搭建HTTPs服务器

var fs = require('fs');
var options = {
  key: fs.readFileSync('E:/ssl/myserver.key'),
  cert: fs.readFileSync('E:/ssl/myserver.crt'),
  passphrase: '1234'
};

var https = require('https');
var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('Hello World Expressjs');
});

var server = https.createServer(options, app);
server.listen(8084);
console.log('Server is running on port 8084');

 

四、静态网页模板

在项目目录之中,建立一个子目录views,用于存放网页模板。

假定这个项目有三个路径:根路径(/)、自我介绍(/about)和文章(/article)。那么,app.js可以这样写:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
res.sendFile(__dirname + '/views/index.html');
});

app.get('/about', (req, res) => {
res.sendFile(__dirname + '/views/about.html');
});

app.get('/article', (req, res) => {
res.sendFile(__dirname + '/views/article.html');
});

app.listen(3000);



上面代码表示,三个路径分别对应views目录中的三个模板:index.html、about.html和article.html。另外,向服务器发送信息的方法,从send变成了sendfile,后者专门用于发送文件。

 

5、动态网页模板

1、安装引擎

Express支持多种模板引擎,这里采用Handlebars模板引擎的服务器端版本hbs模板引擎。

先安装hbs。(npm install hbs --save-dev

上面代码将hbs模块,安装在项目目录的子目录node_modules之中。save-dev参数表示,将依赖关系写入package.json文件。安装以后的package.json文件变成下面这样:

// package.json文件

{
"name": "demo",
"description": "My First Express App",
"version": "0.0.1",
"dependencies": {
"express": "3.x"
},
"devDependencies": {
"hbs": "~2.3.1"
}
}



安装模板引擎之后,就要改写app.js。
// app.js文件

var express = require('express');
var app = express();

// 加载hbs模块
var hbs = require('hbs');

// 指定模板文件的后缀名为html
app.set('view engine', 'html');

// 运行hbs模块
app.engine('html', hbs.__express);

app.get('/', function (req, res){
res.render('index');
});

app.get('/about', function(req, res) {
res.render('about');
});

app.get('/article', function(req, res) {
res.render('article');
});

上面代码改用render方法,对网页模板进行渲染。render方法的参数就是模板的文件名,默认放在子目录views之中,后缀名已经在前面指定为html,这里可以省略。所以,res.render(‘index’) 就是指,把子目录views下面的index.html文件,交给模板引擎hbs渲染。

5.2、新建数据脚本

渲染是指将数据代入模板的过程。实际运用中,数据都是保存在数据库之中的,这里为了简化问题,假定数据保存在一个脚本文件中。

在项目目录中,新建一个文件blog.js,用于存放数据。blog.js的写法符合CommonJS规范,使得它可以被require语句加载。

// blog.js文件

var entries = [
{"id":1, "title":"第一篇", "body":"正文", "published":"6/2/2013"},
{"id":2, "title":"第二篇", "body":"正文", "published":"6/3/2013"},
{"id":3, "title":"第三篇", "body":"正文", "published":"6/4/2013"},
{"id":4, "title":"第四篇", "body":"正文", "published":"6/5/2013"},
{"id":5, "title":"第五篇", "body":"正文", "published":"6/10/2013"},
{"id":6, "title":"第六篇", "body":"正文", "published":"6/12/2013"}
];

exports.getBlogEntries = function (){
return entries;
}

exports.getBlogEntry = function (id){
for(var i=0; i < entries.length; i++){
if(entries[i].id == id) return entries[i];
}
}


5.3、新建网页模板

接着,新建模板文件index.html。

<!-- views/index.html文件 -->

<h1>文章列表</h1>

{{#each entries}}
<p>
<a href="/article/{{id}}">{{title}}</a><br/>
Published: {{published}}
</p>
{{/each}}



模板文件about.html。

<!-- views/about.html文件 -->

<h1>自我介绍</h1>

<p>正文</p>


模板文件article.html。

<!-- views/article.html文件 -->

<h1>{{blog.title}}</h1>
Published: {{blog.published}}

<p/>

{{blog.body}}


可以看到,上面三个模板文件都只有网页主体。因为网页布局是共享的,所以布局的部分可以单独新建一个文件layout.html。

<!-- views/layout.html文件 -->

<html>

<head>
<title>{{title}}</title>
</head>

<body>

{{{body}}}

<footer>
<p>
<a href="/">首页</a> - <a href="/about">自我介绍</a>
</p>
</footer>

</body>
</html>


5.4、渲染模板

最后,改写app.js文件。

 

// app.js文件

var express = require('express');
var app = express();
var bodyParser = require('body-parser')
var hbs = require('hbs');

// 加载数据模块
var blogEngine = require('./blog');

app.set('view engine', 'html');
app.engine('html', hbs.__express);
app.use(bodyParser.json());

app.get('/', function(req, res) {
res.render('index',{title:"最近文章", entries:blogEngine.getBlogEntries()});
});

app.get('/about', function(req, res) {
res.render('about', {title:"自我介绍"});
});

app.get('/article/:id', function(req, res) {
var entry = blogEngine.getBlogEntry(req.params.id);
res.render('article',{title:entry.title, blog:entry});
});

app.listen(3000);



注:

Node中的核心模块分两类:一类是自带的核心模块,如http、tcp等,第二类是第三方核心模块,express就是与http对应的第三方核心模块,用于处理http请求。express在3.0版本中自带有很多中间件,但是在express 4.0以后,就将除static(静态文件处理)以外的其他中间件分离出来了;在4.0以后需要使用中间件时,就需要单独安装好相应的中间件以后调用,以下3.0与4.0中间件的中间件区别(3.0是内置中间件属性名,4.0是需要安装的中间件名称):


 


Express 3.0 Name

Express 4.0 Name

bodyParser

body-parser

compress

compression

cookieSession

cookie-session

logger

morgan

cookieParser

cookie-parser

session

express-session

favicon

static-favicon

response-time

response-time

error-handler

errorhandler

method-override

method-override

timeout

connect-timeout

vhost

vhost

csrf

csurf

 



上面代码中的render方法,现在加入了第二个参数,表示模板变量绑定的数据。

现在重启node服务器,然后访问http://127.0.0.1:3000。

 

 

http://blog.csdn.net/ganxunzou/article/details/42918015

posted @ 2017-12-22 18:05  pyj063  阅读(296)  评论(0编辑  收藏  举报