• 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

  • 相关阅读:
    2016第5周四
    2016第5周三
    2016第5周二
    HTTP2.0那些事
    2016第4周日
    【C语言的日常实践(十二)】命令行参数
    Oracle改变字段类型
    Codeforces Round #269 (Div. 2)
    linux shell 命令
    Codeforces Round #256 (Div. 2) C. Painting Fence 或搜索DP
  • 原文地址:https://www.cnblogs.com/pyj63/p/8087196.html
Copyright © 2020-2023  润新知