forked from expressjs/expressjs.com
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathguide.html
206 lines (200 loc) · 13.3 KB
/
guide.html
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
<!DOCTYPE html><html><head><title>Express - 新手指南</title><link rel="stylesheet" href="/style.css"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="keywords" content="node.js express 中文文档, node express 中文, node express中文文档, express 翻译 api, expressjs 文档, exress框架 中文手册, node expressjs 中文文档, expressjs 中文文档, node express中文, Express框架的中文, express 中文 node, node.js网络应用, express node 文档, express.js 中文, express 中文文档"><script src="http://libs.baidu.com/jquery/1.7.2/jquery.js"></script><script src="/app.js"></script><script src="/retina.js"></script></head><body class="inner"><div class="bar"></div><section id="content"><header><section id="logo"><span class="express">express<em>3.0.4</em></span><span class="description">
web application framework for <a href="http://nodejs.org">node </a></span></section><nav class="clearfix"><a href="/" target="_self"> 首页</a><a href="/3x_zh-cn/api.html" target="_self"> API 参考</a><a href="/guide.html" target="_self" class="active"> 新手指南 </a><a href="/applications.html" target="_self"> 应用展示</a><a href="/community.html" target="_self"> 社区</a><a href="/faq.html" target="_self"> 问答</a><a href="/jade.html" target="_self"> Jade文档</a><a href="/4x_zh-cn/api.html" target="_self"> 4.x文档</a><a href="http://www.ksmimi.com/dashixiongwx/shop/1/article/508" target="_blank"> 工作机会</a><a href="http://123.jser.us" target="_blank"> 前端导航站 </a></nav></header><ul id="menu"><li><ul class="active"><li><a href="#intro">开始 </a></li><li><a href="#executable">可执行的express(1)</a></li><li><a href="#error-handling">错误处理</a></li><li><a href="#users-online">在线用户计数</a></li><li><a href="#proxies">在Express前加一层代理 </a></li><li><a href="#debugging-express">调试 Express</a></li></ul></li></ul><section><h3 id="intro">开始</h3><p>在确认已经安装了node之后(<a href="http://nodejs.org/#download">下载</a>),
在你的机器上创建一个目录,让我们来开始你的第一个应用程序吧
</p><pre class="js"><code>$ mkdir hello-world
</code></pre><p>在这个目录中你首先得定义一下你的应用程序“包”文件,它和其它的node程序包是一样的。
你得在这个目录中创建一个package.json文件,在里面express作为一个依赖。
你也可以使用 <code>npm info express version</code> 来获取express最新的版本号,
最好使用最新的版本号而不是下面的3.x,这样新出的功能就不会让你感觉到奇怪了。
</p><pre class="js"><code>{
"name": "hello-world",
"description": "hello world test app",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "3.x"
}
}
</code></pre><p>现在package.json文件已经准备好了,使用<code>npm(1)</code> 安装依赖,
这里的依赖仅仅是Express。
</p><pre class="js"><code>$ npm install
</code></pre><p>当npm完成后,Express 3.x 和它的依赖就安装到你的 ./node_modules 目录里了。
你可以通过 <code>npm ls</code> 来确认一下,它会把Express 和它的依赖展示成下面的树状结构。
</p><pre class="js"><code>$ npm ls
[email protected] /private/tmp
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
│ └── [email protected]
</code></pre><p>现在我们来写真正的代码了!创建一个名为app.js 或者 server.js的文件,叫什么看你个人喜好了。
载入express 然后使用代码 <code>express()</code>创建一个新的应用程序:
</p><pre class="js"><code>var express = require('express');
var app = express();
</code></pre><p>在这个应用程序实例里,你可以通过 <code>app.VERB()</code>定义路由,下面的例子是"GET /"返回
"Hello World" 字符串。
<code>req</code> 和 <code>res</code> 对象是和node原生提供给你的一致的,你也可以执行
<code>res.pipe()</code>, <code>req.on('data', callback)</code> 等任何事情在没有Express的情况下可以做的事情。
</p><p>Express 给这些对象加了一个封装好的方法,比如
<code>res.send()</code>, 它会帮你设置Content-Length:
</p><pre class="js"><code>app.get('/hello.txt', function(req, res){
res.send('Hello World');
});
</code></pre><p>现在我们通过执行 <code>app.listen()</code> 来绑定并监听连接。
它接受的参数和node<a href="http://nodejs.org/api/net.html#net_server_listen_port_host_backlog_listeninglistener">net.Server#listen()</a>的方法一致:
</p><pre class="js"><code>var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});</code></pre></section><section><h3 id="executable">使用express(1) 来生成一个应用程序</h3><p>Express团队维护了一个可以快速生成项目模板的可执行文件,这里命名为 <code>express(1)</code>.
如果你使用npm全局安装的express-generator, 在你的机器任何位置它都是可用的:
</p><pre class="js"><code>$ npm install -g express-generator
</code></pre><p>这个工具提供了一个非常简单的生成一个程序骨架的功能,但是它也有局限,比如它只支持很少的几个模板引擎。
而事实上Express几乎支持所有的为node所建的模板引擎。
使用 <code>--help</code>查看一下帮助:
</p><pre class="js"><code>Usage: express [options]
Options:
-h, --help 输出帮助信息
-V, --version 输出版本号
-e, --ejs 添加 ejs 模板引擎支持 (默认为jade)
-H, --hogan 添加 hogan.js模板引擎支持
-c, --css <engine> 样式 <引擎> 支持 (less|stylus) (默认为css)
-f, --force 强制在非空目录执行</code></pre><p>如果你想生成一个支持Jade, Stylus的应用程序,只需要简单的执行下面的命令:
</p><pre class="js"><code>$ express --sessions --css stylus --ejs myapp
create : myapp
create : myapp/package.json
create : myapp/app.js
create : myapp/public
create : myapp/public/javascripts
create : myapp/public/images
create : myapp/public/stylesheets
create : myapp/public/stylesheets/style.styl
create : myapp/routes
create : myapp/routes/index.js
create : myapp/views
create : myapp/views/index.jade
create : myapp/views/layout.jade
install dependencies:
$ cd myapp && npm install
run the app:
$ DEBUG=myapp node app
</code></pre><p>和其它node程序一样,你必须安装依赖:
</p><pre class="js"><code>$ cd myapp
$ npm install
</code></pre><p>然后让我们运行它吧!
</p><pre class="js"><code>$ node app
</code></pre><p>这些就是一个简单的应用程序创建和运行的所有步骤。
记住Express没有限定任何的目录结构,这只是一个方便你工作的基本结构。
如果你想得到更多怎么组织目录结构选择,可以查看github上的<a href="https://github.com/visionmedia/express/tree/master/examples">示例</a>。</p></section><section><h3 id="error-handling">错误处理</h3><p>错误处理的中间件和普通的中间件定义是一样的,
只是它必须有4个形参,这是它的形式:
<code>(err, req, res, next)</code>:
</p><pre class="js"><code>app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
</code></pre><p>一般来说非强制性的错误处理一般被定义在最后,下面的代码展示的就是放在别的
<code>app.use()</code> 之后:
</p><pre class="js"><code>app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(function(err, req, res, next){
// logic
});
</code></pre><p>在这些中间件里的响应是可以任意定义的。只要你喜欢,你可以返回任意的内容,譬如HTML页面, 一个简单的消息,或者一个JSON字符串。
</p><p>对于一些组织或者更高层次的框架,你可能会像定义普通的中间件一样定义一些错误处理的中间件。
假设你想定义一个中间件区别对待通过XHR和其它请求的错误处理,你可以这么做:
</p><pre class="js"><code>app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
</code></pre><p>通常<code>logErrors</code>用来纪录诸如stderr, loggly, 或者类似服务的错误信息:
</p><pre class="js"><code>function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}
</code></pre><p><code>clientErrorHandler</code> 定义如下,注意错误非常明确的向后传递了。
</p><pre class="js"><code>function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.send(500, { error: 'Something blew up!' });
} else {
next(err);
}
}
</code></pre><p>下面的<code>errorHandler</code> "捕获所有" 的异常, 定义为:
</p><pre class="js"><code>function errorHandler(err, req, res, next) {
res.status(500);
res.render('error', { error: err });
}</code></pre></section><section><h3 id="users-online">在线用户计数</h3><p>这一小节我们讲解一个小而全的应用程序,它通过<a href="http://redis.io">Redis</a>记录在线用户数。
首先你需要创建一个package.json 文件,包含两个依赖,
一个是redis 客户端,另一个是Express。
另外需要确认你安装了redis, 可以能过执行<code>$ redis-server</code>来确认:
</p><pre class="js"><code>{
"name": "app",
"version": "0.0.1",
"dependencies": {
"express": "3.x",
"redis": "*"
}
}
</code></pre><p>接下来你需要你创建一个应用程序,和一个redis连接:
</p><pre class="js"><code>var express = require('express');
var redis = require('redis');
var db = redis.createClient();
var app = express();
</code></pre><p>接下来是纪录用户在线的中间件。
这里我们使用sorted sets, 它的一个好处是我们可以查询最近N毫秒内在线的用户。
我们通过传入一个时间戳来当作成员的"score"。
注意我们使用 User-Agent 作为一个标识用户的id。
</p><pre class="js"><code>app.use(function(req, res, next){
var ua = req.headers['user-agent'];
db.zadd('online', Date.now(), ua, next);
});
</code></pre><p>下一个中间件是通过<strong>zrevrangebyscore</strong>来查询上一分钟在线用户。
我们将能得到从当前时间算起在60,000毫秒内活跃的用户。
</p><pre class="js"><code>app.use(function(req, res, next){
var min = 60 * 1000;
var ago = Date.now() - min;
db.zrevrangebyscore('online', '+inf', ago, function(err, users){
if (err) return next(err);
req.online = users;
next();
});
});
</code></pre><p>最后我们来使用它,绑定到一个端口!这些就是这个程序的一切了,在不同的浏览器里访问这个应用程序,你会看到计数的增长。
</p><pre class="js"><code>app.get('/', function(req, res){
res.send(req.online.length + ' users online');
});
app.listen(3000);</code></pre></section><section><h3 id="proxies">给Express加一层代理</h3><p>在Express的前端使用一个反向代理,比如 Varnish 或者 Nginx是非常常见的,它不需要额外的配置。
在通过<code>app.enable('trust proxy')</code>激活了"trust proxy" 设置后,
Express 就会知道它在一个代理的后面,<code>X-Forwarded-*</code> 必须被信任,
通常情况下这些头是很容易被伪装的。
</p><p>使用了这个设置后会有一些很棒的小变化。
首先由代理设置的<code>X-Forwarded-Proto</code> 会告诉程序它是https 还是http 。
这个值会影响<a href="/api#req.protocol">req.protocol</a>.
</p><p>第二个变化是 <a href="/api#req.ip">req.ip</a> 和 <a href="/api#req.ips">req.ips</a> 的值会被<code>X-Forwarded-For</code>列表里的地址取代。</p></section><section><h3 id="debugging-express">调试 Express</h3><p>Express使用 <a href="https://github.com/visionmedia/debug">debug</a> 模块
来输出信息。如果想看到这些信息,可以在运行你的程序时设置 <code>DEBUG</code> 环境变量为
<code>express:*</code> ,调试信息会输出在终端里 。
</p><pre class="sh"><code>$ DEBUG=express:* node app.js
</code></pre><p>使用上面的方式运行 <code>hello world</code> 的例子,将会输出下面的内容
</p><pre class="sh"><code>express:application booting in development mode +0ms
express:router defined get /hello.txt +0ms
express:router defined get /hello.txt +1ms
</code></pre><p>获取更多关于 <code>debug</code>的信息,可以查看 <a href="https://github.com/visionmedia/debug">debug 文档</a></p></section></section><script>(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'hm.baidu.com/h.js?47a437a0834ace3da0dac1156ed8369f';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script><a id="top" href="#"><img src="/images/arrow.png"></a><footer><div id="footer-content">© 2012 TJ Holowaychuk. 版权所有. <a href="http://jser.me">草依山</a>翻译</div></footer></body></html>