Express.js的初学者教程

136 阅读10分钟

在这个Express初学者教程中,我们可以下载并安装Express.js到我们的系统中,看看如何设置和配置一个超级基本的骨架应用程序。值得庆幸的是,有一个专门的工具可以自动创建一个新的Express项目,叫做Express Generator,这让我们的工作变得相当容易。让我们来看看完全的初学者如何能够马上使用Express.js来运行。


什么是Express.js,我们为什么要使用它?

所以在这一点上,我们已经花了一些时间来习惯在非常基本的水平上使用Node.js。我们了解了什么是Node.js,如何从文件系统中写入和读取数据,处理一些请求和响应,以及建立我们自己的基本路由系统。如果你看一下路由教程中的代码,你会注意到,仅靠我们自己建立一些路由是有点费劲的。此外,如果我们想添加多个路由,它的规模就不会那么大了。以纯粹的形式使用Node.js,需要我们自己编写所有的东西。这很容易出错,很可能不安全,而且只是普通的大量工作。你猜怎么着?就像软件开发中的大多数其他事情一样,你想做的事情很可能已经有了稳定的、经过测试的解决方案。这就是为什么我们现在要看一下Express.js。Express将允许你专注于你的业务逻辑和你的应用程序的需求。像解析尿液和设置手动路由这样的重复性任务可以由该框架来处理。Express建立在Node的基础上,提供了许多工具,使Node的工作更容易。有了Express,配置路由变得轻而易举。由TJ Holowaychuk创建的Express框架为许多常见的任务提供了方便的方法和语法糖,否则这些任务将是乏味和多余的。


如何设置和配置Express.js

我们需要做的第一件事是在我们的系统上安装Express生成器模块。这是很简单的事情。只要在你的命令行中输入npm install -g express-generator ,这将为你安装它。

C:node>npm install -g express-generator

接下来,让我们继续使用我们新安装的Express Generator创建一个新的Express项目。你所要做的就是输入express ,然后再输入你要创建的项目的名称。我们将创建一个名为expressjs-tutorial 的项目。你会看到,当生成器工作时,它会给你一些输出,告诉你它为你的项目创建的确切文件和文件夹。

C:node>express expressjs-tutorial

  warning: the default view engine will not be jade in future relea
  warning: use `--view=jade' or `--help' for additional options


   create : expressjs-tutorial
   create : expressjs-tutorialpublic
   create : expressjs-tutorialpublicjavascripts
   create : expressjs-tutorialpublicimages
   create : expressjs-tutorialpublicstylesheets
   create : expressjs-tutorialpublicstylesheetsstyle.css
   create : expressjs-tutorialroutes
   create : expressjs-tutorialroutesindex.js
   create : expressjs-tutorialroutesusers.js
   create : expressjs-tutorialviews
   create : expressjs-tutorialviewserror.jade
   create : expressjs-tutorialviewsindex.jade
   create : expressjs-tutorialviewslayout.jade
   create : expressjs-tutorialapp.js
   create : expressjs-tutorialpackage.json
   create : expressjs-tutorialbin
   create : expressjs-tutorialbinwww

   change directory:
     > cd expressjs-tutorial

   install dependencies:
     > npm install

   run the app:
     > SET DEBUG=expressjs-tutorial:* & npm start

在这个例子中,我们现在使用Visual Studio Code,选择 "Open Folder "选项来打开刚刚创建的文件夹。
express generator folder structure


Package.json

作为项目创建的一部分,Express Generator填写了一个package.json文件,该文件提供了在Express中创建一个骨架程序所需的依赖性列表。
package.json

{
  "name": "expressjs-tutorial",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.16.0",
    "http-errors": "~1.6.2",
    "jade": "~1.11.0",
    "morgan": "~1.9.0"
  }
}

这些依赖项还没有安装,所以你需要换到存放package.json的目录中,并运行 npm install来完成这一过程。

C:node>cd expressjs-tutorial

C:nodeexpressjs-tutorial>npm install

一旦这个步骤完成,你现在就会有一个node_modules文件夹,它实际上保存了所有这些刚刚用npm下载到你机器上的依赖项。
node_modules folder holds dependencies


启动Express!

你已经准备好启动Express应用程序了。要做到这一点,只需在项目的根部输入npm start

C:nodeexpressjs-tutorial>npm start

> expressjs-tutorial@0.0.0 start C:nodeexpressjs-tutorial
> node ./bin/www

现在,继续打开你的浏览器,在http://localhost:3000/,看看吧
welcome to express


bin/wwwapp.js 文件

这两个文件在Express应用程序中是非常重要的,所以让我们快速看一下它们为我们做什么。


www 服务器文件

/bin/www 文件是 Express 的应用程序入口。它所做的第一件事就是要求() "真正的 "应用程序入口,也就是app.js,它设置并返回 express() 应用程序对象。下面是该文件中包含的代码。

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('expressjs-tutorial:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string' ?
    'Pipe ' + port :
    'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string' ?
    'pipe ' + addr :
    'port ' + addr.port;
  debug('Listening on ' + bind);
}

下面是Express中的bin/www服务器文件的一些快速启示。

var app = require('.../app');app文件在这里被加载。

var debug = require('debug')('expressjs-tutorial:server');设置服务器调试和名称。

var http = require('http');Load the http module that we learned about in thehtml rendering tutorial.

var port = normalizePort(process.env.PORT || '3000');将'3000'的字符串值变成一个整数。

app.set('port', port);设置应用程序应使用的监听端口。

var server = http.createServer(app);像我们在Node路由教程中看到的那样创建服务器。

server.listen(port);
server.on('error', onError);
server.on('listening', onListening)
;设置了监听以及错误和监听事件。


app.js 文件

app.js文件创建了一个Express应用程序对象,按惯例命名为app,并通过各种设置和中间件设置了该应用程序。然后,它从模块中导出应用程序。下面是app.js文件中的代码。

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({
  extended: false
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

在文件的顶部,有几个导入,Express需要它们来进行工作。

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

这是Express在你第一次用Express Generator创建项目时提供的两个示例路由。

var app = express();
应用程序在这里被创建。

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade')
;在这里你可以配置使用的模板引擎。默认情况下,它使用Jade

set views directory node jade

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({
extended: false
}));
app.use(cookieParser())
;这里是指定logger、json、urlencoded和cookie解析器的中间程序。

**app.use(express.static(path.join(__dirname, 'public')));**如何在Express中设置公共文件夹。

set express public folder

app.use('/', indexRouter);
app.use('/users', usersRouter)
;这里指定了//users 的基本路由。


检查index.jsusers.js 路由文件

我们可以看到,在app.js文件中,如果一个用户请求/ 路由,那么indexRouter就会被这个代码使用app.use('/', indexRouter); 。现在indexRouter实际上持有index.js中包含的内容。这是由var indexRouter = require('./routes/index'); ,让我们看一下那个文件。


routes/index.js

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

这里是行动开始发生的地方。在文件的顶部,express router被要求并被初始化到router 这个变量中。之后,我们可以看到,一个get()函数被调用。该函数接受两个参数。

第一个参数是路由的路径。当然,在这种情况下,它只是/ 或主页。

第二个参数是一个函数,它本身需要三个参数。这个函数接收请求、响应和下一个参数。

在这个函数中,对render()进行了调用。我们可以看到,"index "是第一个参数。这是说要在views文件夹中寻找一个扩展名为index的文件。在views文件夹中,有一个index.jade文件。这就是被引用的文件。render()函数的第二个参数是一个JavaScript对象。正是在这个对象中,变量数据可以在渲染过程中传递给视图。事实上,让我们对这个文件做一个快速的修改。

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'I am learning Express!' });
});

module.exports = router;

在命令行中输入ctrl-c,重新启动应用程序。

Terminate batch job (Y/N)? y

npm start重新启动

C:nodeexpressjs-tutorial>npm start

一旦服务器重启,你可以看到,通过更新JavaScript对象的标题属性,我们的数据在网络浏览器中被更新。
indes route expressjs

关键的概念是,我们正在渲染一个模板文件,并将动态数据传入该文件,以便在视图中使用。这个概念在许多不同的框架和许多不同的编程语言中都是一样的。


子路线

现在我们可以看一下 users.js 文件。


users.js

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;

注意到什么了吗?users.js文件使用的是相同的/ 路径。这怎么可能呢?这是因为在app.js中,已经定义了/users 将使用 users.js。因此,users.js,我们不需要指定完整的/users路径。事实上,如果我们这样做,那就等于/users/users ,这不是我们想要的。关键是在实际路由文件中看到的路径是相对于app.js中指定的路径。为了了解这一点,我们可以向users.js添加另一个路由。

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function (req, res, next) {
  res.send('respond with a resource');
});

router.get('/stats', function (req, res, next) {
  res.send('Stats about the user');
});

module.exports = router;

这样做的目的是建立一个新的路由,可以访问http://localhost:3000/users/stats
sub route express example


单一文件路由

我们现在看到了路由在新安装的Express.js上是如何工作的。也许你更希望有一个单一的入口,把你所有的路由放在一个文件中。如果你愿意,你也可以这样做。让我们来看看怎么做。

首先,从app.js中删除var usersRouter = require('./routes/users'); 。
remove users route

接下来,从app.js中删除app.use('/users', usersRouter); 。
remove app-use users

最后,你可以像这样把所有的路由合并到index.js文件中。

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function (req, res, next) {
  res.render('index', {
    title: 'I am learning Express!'
  });
});

/* GET users listing. */
router.get('/users', function (req, res, next) {
  res.send('respond with a resource');
});

router.get('/users/stats', function (req, res, next) {
  res.send('Stats about the user');
});

module.exports = router;

但是请注意,当把所有的路由放在同一个文件中时,我们需要指定完整的路径,而不是把每个路由放在自己的文件中。这两种方法都可以,这取决于什么对你和你的需求最有意义。我们现在看到了一个基本骨架的Express应用程序是如何设置的,以及它是如何工作的。


Express.js初学教程总结

你现在已经使用Express Generator创建了一个骨架网站项目,并确认它使用node运行。通过查看为我们创建的文件和文件夹,你也明白了一个Express应用程序是如何结构化的。这里有一些关于Express和Node的关键话题需要记住。

  • Express通过遵循请求处理管道架构来工作
  • 一个Express应用程序主要是一个中间件函数的集合,所有的中间件函数都在一起工作。
  • 一个中间件函数是一个接受请求对象的函数,它要么终止请求/响应周期,要么将控制权传递给另一个中间件函数。
  • Express有几个内置的中间件功能
    • json(): 用来解析带有JSON有效载荷的请求正文。
    • urlencoded(): 用来解析带有URL编码的有效载荷的请求正文。
    • static(): 用来提供静态文件
  • 任何人都可以创建自定义中间件并在请求处理管道中使用它
// Custom middleware (applied on all routes)
app.use(function(req, res, next)) {
// …
next();
}
// Custom middleware (applied on routes starting with /api/v1)
app.use(‘/api/v1’, function(req, res, next)) {
// …
next();
}
  • 你可以使用process.env.NODE_ENV和app.get('env')检测我们的Node应用程序的运行环境。
  • config包是为我们的应用程序存储配置设置的一个好方法。
  • 我们可以使用debug包来为应用程序添加调试信息,以获得比console.log()更多的权力。
  • 你可以使用模板引擎来向客户端返回HTML标记。Jade(Pug)、EJS和Mustache是最流行的。