1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
|
---
title: Express 教程 2:创建站点框架
slug: learn/Server-side/Express_Nodejs/skeleton_website
tags:
- Express
- Node
- node.js
- npm
- 入门
- 初学者
- 学习
- 开发环境
- 服务器端
- 服务器端编程
translation_of: Learn/Server-side/Express_Nodejs/skeleton_website
---
<div>{{LearnSidebar}}</div>
<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}</p>
<p class="summary">本节将演示如何创建一个可添加路由、模板/视图、和数据库调用的“骨架”站点。</p>
<table class="learn-box standard-table">
<tbody>
<tr>
<th scope="row">预备知识:</th>
<td><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/development_environment">配置 Node 开发环境</a>。复习 Express 教程。</td>
</tr>
<tr>
<th scope="row">目标:</th>
<td>掌握用 <strong>Express 应用生成器</strong> 创建站点的方法。</td>
</tr>
</tbody>
</table>
<h2 id="概览">概览</h2>
<p>本节演示了如何使用 <a href="http://www.expressjs.com.cn/starter/generator.html">Express 应用生成器</a> 创建一个可添加路由、模板/视图和数据库调用的“骨架”网站。这里我们将使用该生成器为 <a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">本地图书馆网站</a> 创建框架,以便在以后章节添加其它代码。过程非常简单,只需要在命令行运行 “生成器 + 项目名称” 即可,此外还可以指定站点的模板引擎和 CSS 生成器。</p>
<p>以下内容介绍了应用生成器的用法,以及视图 / CSS 的一些不同选项。还介绍了骨架站点的组织结构。最后,我们将介绍站点的运行方法,从而对其进行验证。</p>
<div class="note">
<p><strong>注:</strong>Express 应用生成器并非唯一的 Express 应用生成工具,而且生成项目的结构也不是组织文件和目录的唯一可行方式。但生成项目具有易于扩展和理解的模块化结构。最简单的 Express 应用请参阅 <a href="http://expressjs.com.cn/starter/hello-world.html">Hello world 示例</a>(Express 镜像站)。</p>
</div>
<h2 id="使用应用生成器">使用应用生成器</h2>
<div class="blockIndicator note">
<p><strong>译注:</strong>本教程中命令操作基于 Linux/macOS 的 bash 终端,Windows 的命令提示符 cmd/PowerShell 与 bash 的概念和用法略有不同, 为在 Windows 上获得一致的体验,可以:</p>
<ul>
<li>自己弄懂 cmd/PowerShell 与 bash 的区别。</li>
<li>使用 <a href="https://git-scm.com/">Git</a> 或 <a href="http://www.msys2.org/">MSYS2</a> 为 Windows 提供的 bash。(推荐)</li>
<li>使用 Windows 的 Linux 子系统。(到 Microsoft Store 中搜索“Linux”,安装喜欢的版本(Ubuntu 18.04、openSUSE 42、Debian 等),仅限 Windows 10,使用前需要先安装 <a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10">WSL</a>)</li>
</ul>
</div>
<div class="blockIndicator note">
<p><strong>译注:</strong>你可能已经发现国内用 NPM 太慢了!这是由众所周知的不可抗力造成的。可用淘宝提供的 <a href="https://npm.taobao.org/">CNPM</a> 代替之,功能和用法基本一致(只是不能上传自己的包)。</p>
</div>
<p>你应该已经安装好了生成器,它是 <a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/development_environment">设置 Node 开发环境</a> 的一部分。可以使用 NPM 来安装全局的生成器,如下所示:</p>
<pre class="brush: bash notranslate">$ sudo npm install express-generator -g</pre>
<p>生成器有许多选项,可以使用 <code>--help</code>(或 <code>-h</code>)命令进行查看:</p>
<p><img alt="express 生成器的帮助信息" src="https://mdn.mozillademos.org/files/16407/express-help.png"></p>
<p>大意如下:</p>
<pre class="brush: bash notranslate">$ express --help
用法:express [选项] [目录]
选项:
--version 打印版本号
-e, --ejs 添加 ejs 引擎支持
--pug 添加 pug 引擎支持
--hbs 添加 handlebars 引擎支持
-H, --hogan 添加 hogan.js 引擎支持
-v, --view <engine> 添加 <engine> 试图引擎支持 (ejs|hbs|hjs|jade|pug|twig|vash) (默认为 jade)
-c, --css <engine> 添加 <engine> 样式表引擎支持 (less|stylus|compass|sass) (默认为纯 css)
--git 添加 .gitignore
-f, --force 对非空文件夹强制执行
-h, --help 打印帮助信息
</pre>
<p>可以直接运行 express 命令,将使用 Jade 视图引擎和纯 CSS 在当前目录中创建项目。(如果指定目录名,则在子目录中创建项目)。</p>
<pre class="brush: bash notranslate">$ express</pre>
<p>还可以使用 <code>--view</code> 选择视图(模板)引擎,并且/或者使用 <code>--css</code> 选择 CSS 生成引擎。</p>
<div class="note">
<p><strong>注:</strong>不推荐用 <code>--hogan</code>、<code>--ejs</code>、<code>--hbs</code> 等参数选用模板引擎。请使用 <code>--view</code>(或 <code>-v</code>)。</p>
</div>
<h3 id="我应该用哪个视图引擎?">我应该用哪个视图引擎?</h3>
<p>Express 应用生成器支持多款流行的视图/模板引擎,包括 <a href="https://www.npmjs.com/package/ejs">EJS</a>、<a href="http://github.com/donpark/hbs">Hbs</a>、<a href="https://pugjs.org/api/getting-started.html">Pug</a> (Jade)、<a href="https://www.npmjs.com/package/twig">Twig</a> 和 <a href="https://www.npmjs.com/package/vash">Vash</a>,缺省选项是 Jade。Express 本身也支持大量其他模板语言,<a href="https://github.com/expressjs/express/wiki#template-engines">开箱即用</a>。</p>
<div class="note">
<p><strong>注:</strong>如果要使用生成器不支持的模板引擎,请参阅 <a href="http://expressjs.com.cn/guide/using-template-engines.html">在 Express 中使用模板引擎</a>(Express 文档)和所选视图引擎的文档。</p>
</div>
<p>一般来说,你应该选择一个大而全的模板引擎,可以尽快进入生产状态。就像你选择其他组件一样!选用模板引擎需要考虑以下因素:</p>
<ul>
<li>进入生产状态的时间——如果你的团队已经有某个模板语言的经验,那么用它可能更快进入生产状态。否则你应该考虑所选模板引擎的学习曲线。</li>
<li>流行度和活跃度——要评估所选引擎的流行程度,以及它是否拥有活跃的社区。在网站的生命周期中遇到问题时,是否能够获得相关支持非常重要。</li>
<li>风格——某些模板引擎使用特定标记,来标识插入“普通” HTML 中的内容,而另一些模板引擎使用不同的语法(例如使用缩进和块名称)构造 HTML。</li>
<li>性能/渲染时间。</li>
<li>功能——你应该考虑所选引擎是否具有以下功能:
<ul>
<li>布局继承:可以定义基本模板,然后 “继承” 它的一部分,使不同页面可以有不同的呈现。这通常比包含大量所需组件,或每次从头开始构建模板更好。</li>
<li>“包含”支持:可以通过包含其他模板来构建新模板。</li>
<li>简明的变量和循环控制语法。</li>
<li>能够在模板级别过滤变量值(例如,将变量设置为大写,或格式化日期值)。</li>
<li>能够生成 HTML 以外的输出格式(例如 JSON 或 XML)。</li>
<li>支持异步操作和流。</li>
<li>可以在同时在客户端和服务器上使用。如果一款模板引擎可以在客户端使用,那么就使在客户端托管数据并完成所有(或大多数)渲染成为可能。</li>
</ul>
</li>
</ul>
<div class="note">
<p><strong>提示:</strong>互联网上有许多资源,可帮助你选择合适的视图/模板引擎。</p>
</div>
<p>本项目选用<a href="https://pugjs.org/api/getting-started.html"> Pug </a>模板引擎(Jade 是它不久前的曾用名),它是最流行的 Express / JavaScript 模板语言之一,且对 Express 生成器 <a href="https://github.com/expressjs/express/wiki#template-engines">开箱即用</a>。</p>
<h3 id="我应该用哪个_CSS_引擎?">我应该用哪个 CSS 引擎?</h3>
<p>Express 应用生成器支持最常见的 CSS 引擎:<a href="http://lesscss.org/">LESS</a>, <a href="http://sass-lang.com/">SASS</a>, <a href="http://compass-style.org/">Compass</a>, <a href="http://stylus-lang.com/">Stylus</a>。</p>
<div class="note">
<p><strong>注:</strong>CSS 的一些限制导致某些任务完成起来非常困难。CSS 引擎提供了更强大的语法来定义 CSS,然后将定义编译为纯 CSS 供浏览器使用。</p>
</div>
<p>与模板引擎一样,你也应该使用样式表引擎,这可以最大化团队生产力。本项目将使用原始 CSS(默认的),因为我们对 CSS 要求不复杂,没有必要使用引擎。</p>
<h3 id="我应该用哪个数据库?">我应该用哪个数据库?</h3>
<p>生成器生成的代码不使用、也不包含任何数据库。 Express 应用可以使用 Node 支持的所有 <a href="https://expressjs.com/en/guide/database-integration.html">数据库</a>(Express 本身不提供数据库管理机制)。</p>
<p>我们后续讨论数据库集成问题。</p>
<h2 id="创建项目">创建项目</h2>
<p>我们为本地图书馆应用创建一个名为 express-locallibrary-tutorial 的项目,使用 Pug 模板库,不使用 CSS 引擎。</p>
<p>首先,进入准备放置项目的目录,然后在命令提示符运行 Express 应用生成器,生成器将创建(并列出)项目的文件:</p>
<p><img alt="用 express 生成器生成一个应用" src="https://mdn.mozillademos.org/files/16408/express.png"></p>
<p>生成器在最后还告诉你如何安装(<strong>package.json</strong> 中所列的)依赖,以及如何运行该应用。</p>
<h2 id="运行骨架网站">运行骨架网站</h2>
<p>现在我们已经拥有一个完整的项目骨架。虽然这个网站现在还做不了什么,但运行一下,展示一下工作原理也是值得的。</p>
<ol>
<li>首先,安装依赖项(<code>install</code> 命令将获取项目的 <strong>package.json</strong> 文件中列出的所有依赖项包)。
<pre class="brush: bash notranslate">$ npm install</pre>
</li>
<li>然后运行该应用。
<pre class="brush: bash notranslate">$ DEBUG=express-locallibrary-tutorial:* npm start</pre>
</li>
<li>最后在浏览器中导航至 <a href="http://localhost:3000/">http://localhost:3000/</a> ,就可以访问该应用。你应该可以看到: <img alt="Express 应用生成器生成的应用启动成功" src="https://mdn.mozillademos.org/files/16410/success.png"></li>
</ol>
<p>一个 Express 应用就配置成功了,它托管于 localhost:3000。</p>
<div class="note"><strong>注:</strong>指定 DEBUG 变量可启用控制台日志记录/调试。例如,当你访问上面的页面时,你会看到像这样的调试输出: <img alt="用 npm start 启动这个应用" src="https://mdn.mozillademos.org/files/16409/npm-start.png"> 直接通过 <code>npm start</code> 命令启动应用也可以,但不会看到调试信息。</div>
<h2 id="文件改动时重启服务器">文件改动时重启服务器</h2>
<p>只有重启服务器才能看到 Express 网站所做的改动。每次改动后手动启停服务器实在太烦人了,有必要花点时间让这项工作自动化。</p>
<p><a href="https://github.com/remy/nodemon">nodemon</a> 是最简便的自动化工具之一。通常将其全局安装(因为它是一个“工具”):</p>
<pre class="brush: bash notranslate">$ sudo npm install -g nodemon</pre>
<p>这里还可以把它作为开发依赖将安装在本地,于是使用这个项目的开发人员只要安装这个应用就能自动获得。通过以下命令将其安装在骨架项目的根目录:</p>
<pre class="brush: bash notranslate">$ npm install --save-dev nodemon</pre>
<p>项目的 <strong>package.json</strong> 文件将自动添加一个新的属性:</p>
<pre class="brush: json notranslate"> "devDependencies": {
"nodemon": "^1.18.9"
}
</pre>
<p>如果没有全局安装该工具,就无法从命令行启动它(除非我们将其添加到路径中),但是可以在 NPM 脚本中调用它,因为 NPM 掌握所有已安装包的信息。找到 package.json 的 <code>scripts</code> 部分。在 <code>"start"</code> 一行的末尾添加逗号,并在新的一行中添加 <code>"devstart"</code>,如下所示:</p>
<pre class="brush: json notranslate"> "scripts": {
"start": "node ./bin/www"<strong>,</strong>
<strong> "devstart": "nodemon ./bin/www"</strong>
},
</pre>
<p>现在可以用新建的 <code>devstart</code> 命令启动服务器:</p>
<pre class="brush: bash notranslate">$ DEBUG=express-locallibrary-tutorial:* npm <strong>run devstart</strong></pre>
<p>现在,如果编辑项目中的任何文件,服务器将自动重启(或者可以随时使用 rs 命令来重启)。查看更新后的页面需要点击浏览器的“刷新”按钮。</p>
<div class="note">
<p><strong>注:</strong>这里必须使用“<code>npm <strong>run <em><scriptname></em></strong></code>”命令,而不是 <code>npm start</code>,因为 “start” 本质上是映射到脚本的一条 NPM 命令。我们可以在 <code>start</code> 脚本中替换它,但我们只想在开发期间使用 nodemon,因此有必要创建一条新的脚本命令。</p>
</div>
<h2 id="生成的项目">生成的项目</h2>
<p>我们来看看刚刚创建的项目。</p>
<h3 id="目录结构">目录结构</h3>
<p>安装好依赖项的生成项目具有如下文件结构(<strong>不</strong>带 “/” 前缀的是文件):</p>
<pre class="notranslate">/express-locallibrary-tutorial
<strong>app.js</strong>
/bin
<strong>www</strong>
<strong>package.json</strong>
/node_modules
[约 4,500 个子文件夹和文件]
/public
/images
/javascripts
/stylesheets
<strong>style.css</strong>
/routes
<strong>index.js</strong>
<strong>users.js</strong>
/views
<strong>error.pug</strong>
<strong>index.pug</strong>
<strong>layout.pug</strong>
</pre>
<p><strong>package.json </strong>文件定义依赖项和其他信息,以及一个调用应用入口(<strong>/bin/www</strong>,一个 JavaScript 文件)的启动脚本,脚本中还设置了一些应用的错误处理,加载 <strong>app.js </strong>来完成其余工作。<strong>/routes</strong> 目录中用不同模块保存应用路由。/<strong>views</strong> 目录保存模板。</p>
<p>下面来详细介绍这些文件。</p>
<h3 id="package.json">package.json</h3>
<p><strong>package.json </strong>文件中定义了应用依赖和其他信息:</p>
<pre class="brush: json notranslate">{
"name": "express-locallibrary-tutorial",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
"devstart": "nodemon ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"morgan": "~1.9.0",
"pug": "2.0.0-beta11"
},
"devDependencies": {
"nodemon": "^1.18.9"
}
}
</pre>
<p>依赖包括 <em>express</em> 包,和选用的视图引擎包(<em>pug</em>)。还有以下一些实用的包:</p>
<ul>
<li><a href="https://www.npmjs.com/package/cookie-parser">cookie-parser</a>:用于解析 cookie 头来填充 <code>req.cookies</code>(提供了访问 cookie 信息的便捷方法)。</li>
<li><a href="https://www.npmjs.com/package/debug">debug</a>:一个小型 node 调试程序,仿照 node 核心的调试技术建立。</li>
<li><a href="https://www.npmjs.com/package/http-errors">http-errors</a>:处理错误中间件。</li>
<li><a href="https://www.npmjs.com/package/morgan">morgan</a>:node 专用 HTTP 请求记录器中间件。</li>
</ul>
<p>"<code>scripts</code>" 部分,定义了一个 "<code>start</code>" 脚本,当运行 <code>npm start</code> 时会调用它来启动服务器。在脚本定义中可以看到 <code>start</code> 实际上运行了 "node <strong>./bin/www"</strong>。还有一个 "<code>devstart</code>" 脚本,可以通过运行 <code>npm run devstart</code> 来运行 "nodemon <strong>./bin/www</strong>"。</p>
<pre class="brush: json notranslate"> "scripts": {
"start": "node ./bin/www",
"devstart": "nodemon ./bin/www"
},
</pre>
<h3 id="www_文件">www 文件</h3>
<p>文件 <strong>/bin/www </strong>是应用入口!它做的第一件事是 <code>require()</code> “真实” 的应用入口(即项目根目录中的 <strong>app.js</strong> ),<strong>app.js </strong>会设置并返回 <code><a href="http://expressjs.com/en/api.html">express()</a></code><a href="http://expressjs.com/en/api.html"> </a>应用对象。</p>
<pre class="brush: js notranslate">#!/usr/bin/env node
/**
* Module dependencies.
* 模块依赖项。
*/
<strong>var app = require('../app');</strong>
</pre>
<div class="note">
<p><strong>注:</strong><code>require()</code> 是一个全局的 node 函数,可将模块导入当前文件。这里使用相对路径指定<strong> app.js</strong> 模块,并省略了 .<strong>js</strong> 扩展名(可选)。</p>
</div>
<p>文件的其余部分先为 <code>app</code> 设置端口(环境变量中的预定义值或默认值 3000),再创建一个 HTTP 服务器,然后开始监听请求,报告服务器错误和连接信息。其它内容可暂时忽略(这里所有内容都是机器生成的模板),但感兴趣的话可以随时回来看看。</p>
<h3 id="app.js">app.js</h3>
<p>此文件创建一个 <code>express</code> 应用对象(依照惯例命名为 <code>app</code>),通过各种设置选项和中间件来设置这个应用,然后从该模块中导出。以下代码只展示了文件中创建和导出应用对象的部分:</p>
<pre class="brush: js notranslate"><code>var express = require('express');
var app = express();
...
</code>module.exports = app;
</pre>
<p>上文的<strong> www</strong> 入口文件中 <code>require()</code> 的 <code>app</code> 就是这里导出的 。</p>
<p>我们来详细了解一下<strong> app.js</strong> 文件。首先,它使用 <code>require()</code> 导入了一些实用 node 库,其中包括之前用 NPM 下载的 <code>express</code>,<code>http-errors</code>,<code>morgan</code> 和 <em><code>cookie-parser</code>,还有一个 </em><em><code>path</code> </em>库,它是用于解析文件和目录的核心 node 库。</p>
<pre class="brush: js notranslate">var express = require('express');
var createError = require('http-errors');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var path = require('path');
</pre>
<p>然后 <code>require()</code> 的是用户路由目录中的模块。这些模块/文件用于处理特定的“路由”(URL 路径)。可以通过添加新文件来扩展骨架应用,比如添加图书相关的路由来列出所有馆藏书目。</p>
<pre class="brush: js notranslate">var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
</pre>
<div class="note">
<p><strong>注意:</strong> 此时我们刚刚导入了模块;还没有真正使用过其中的路由(稍后会使用)。</p>
</div>
<p>下面我们用导入的 <code>express</code> 模块来创建 <code>app</code> 对象,然后使用它来设置视图(模板)引擎。设置引擎分两步:首先设置 '<code>views</code>' 以指定模板的存储文件夹(此处设为子文件夹 <strong>/views</strong>)。然后设置 '<code>view engine</code>' 以指定模板库(本例中设为 “pug” )。</p>
<pre class="brush: js notranslate">var app = express();
// view engine setup
// 视图引擎设定
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
</pre>
<p>下一组 <code>app.use()</code> 调用将中间件库添加进请求处理链。除了之前导入的第三方库之外,我们还使用 <code>express.static</code> 中间件将项目 <strong>/public</strong> 目录下所有静态文件托管至根目录。</p>
<pre class="brush: js notranslate">app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
<strong>app.use(express.static(path.join(__dirname, 'public')));</strong>
</pre>
<p>所有中间件都已设置完毕,现在把(之前导入的)路由处理器添加到请求处理链中。从而为网站的不同部分定义具体的路由:</p>
<pre class="brush: js notranslate">app.use('/', indexRouter);
app.use('/users', usersRouter);
</pre>
<div class="note">
<p><strong>注:</strong>这些路径(<code>'/'</code> 和 '<code>/users'</code>)将作为导入路由的前缀。如果导入的模块 <code>users<font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><span style="background-color: #fff3d4;">在</span></font></code><code>/profile</code> 定义了路由,则可以在 <code>/users/profile</code> 访问该路由。我们将在后面的文章中,详细讨论路由。</p>
</div>
<p>最后一个中间件为错误和 HTTP 404 响应添加处理方法。</p>
<pre class="brush: js notranslate">// catch 404 and forward to error handler
// 捕获 404 并抛给错误处理器
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
// 设置 locals,只在开发环境提供错误信息
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');
});
</pre>
<p>Express 应用对象(<code>app</code>)现已完成配置。最后一步是将其添加到 <code>exports</code> 模块(使它可以通过 <strong>/bin/www </strong>导入)。</p>
<pre class="brush: js notranslate">module.exports = app;</pre>
<h3 id="路由">路由</h3>
<p>路由文档 <strong>/routes/users.js </strong>如下所示(由于路由文件均使用类似结构,所以 <strong>index.js</strong> 略过不讲)。首先加载 <code>express</code> 模块并获取 <code>express.Router</code> 对象(命名为 <code>router</code>)。然后为 <code>router</code> 指定路由,最后导出 <code>router</code>(就可以导入 <strong>app.js</strong> 了)。</p>
<pre class="brush: js notranslate">var express = require('express');
var router = express.Router();
/* GET users listing. */
<strong>router.get('/', function(req, res, next) {
res.send('respond with a resource');
});</strong>
module.exports = router;
</pre>
<p>该路由定义了一个回调,在检测到正确模式的 HTTP <code>GET</code> 请求时将调用该回调。正确模式即导入模块时指定的路由('<code>/users</code>')加该模块('<code>/</code>')中定义的任何内容。换句话说,在收到 <code>/users/</code> URL 时使用此路由。</p>
<div class="note">
<p><strong>提示:</strong>用 node 启动该应用并访问 <a href="http://localhost:3000/users/">http://localhost:3000/users/</a>,浏览器会返回一条消息:'respond with a resource'。</p>
</div>
<p>值得注意的是,上述回调函数有第三个参数 '<code>next</code>',因此它是一个中间件函数,而不是简单的路由回调。<code>next</code> 参数暂时还用不到,在 <code>'/'</code> 路径中添加多个路由处理器时才会涉及。</p>
<h3 id="视图(模板)">视图(模板)</h3>
<p>视图(模板)存保存在 <strong>/views</strong> 目录中( <strong>app.js</strong> 中指定),使用 <strong>.pug </strong>扩展名。 <code><a href="http://expressjs.com/en/4x/api.html#res.render">Response.render()</a></code> 方法用某对象的某个变量值一同来渲染一个特定的模板,然后将结果作为响应发送。在 <strong>/routes/index.js</strong> 中可以看到,该路由使用 '<code>index</code>' 模板和一个模板变量 <code>title</code> 来渲染响应。</p>
<pre class="brush: js notranslate">/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
</pre>
<p>以下是上文代码中涉及到的模板(<strong>index.pug</strong>)。pug 语法稍后再详细讨论。现在只需要知道:<code>title</code> 变量将以 <code>'Express'</code> 作为值插入模板的指定位置。</p>
<pre class="notranslate">extends layout
block content
h1= title
p Welcome to #{title}
</pre>
<h2 id="挑战自我">挑战自我</h2>
<p>在 <strong>/routes/users.js</strong> 中添加一个新路由,在URL <code>/users/cool/</code> 处显示文本 "你好酷"。运行服务器,并在浏览器中访问 <a href="http://localhost:3000/users/cool/">http://localhost:3000/users/cool/ </a>,测试一下是否成功。</p>
<ul>
</ul>
<h2 id="小结">小结</h2>
<p>现在你已经为 <a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">本地图书馆</a> 创建好了骨架,并且成功在 node 上运行起来。同时最重要的是,你了解了项目的结构,从而了解了如何为本地图书馆添加路由和视图。</p>
<p>下一节我们开始修改骨架,让它具备一些图书馆网站的功能。</p>
<h2 id="另请参阅">另请参阅</h2>
<ul>
<li><a href="http://www.expressjs.com.cn/starter/generator.html">Express 应用生成器</a> (Express 中文镜像文档)</li>
<li><a href="http://www.expressjs.com.cn/guide/using-template-engines.html">在 Express 中使用模板引擎</a>(Express 镜像文档)</li>
</ul>
<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}</p>
<h2 id="本章目录">本章目录</h2>
<ul>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node 入门</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/development_environment">设置 Node(Express)开发环境</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express 教程:本地图书馆网站</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express 教程 2:创建站点框架</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/mongoose">Express 教程 3:使用数据库(Mongoose)</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/routes">Express 教程 4:路由和控制器</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express 教程 5:显示图书馆数据</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/forms">Express 教程 6:使用表单</a></li>
<li><a href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/deployment">Express 教程 7:部署至生产环境</a></li>
</ul>
|