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
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
|
---
title: 'Учебник Express часть 2: Создание скелета сайта'
slug: Learn/Server-side/Express_Nodejs/skeleton_website
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">Эта вторая статья в нашем <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">учебнике Express</a> показывает, как создать каркас проекта веб-сайта, который позже можно будет заполнить с помощью путей сайта, шаблонов представлений и обращений к базе данных.</p>
<table class="learn-box standard-table">
<tbody>
<tr>
<th scope="row">Необходимые знания:</th>
<td><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Установить среду разработки Node</a>. Просмотреть учебник Express.</td>
</tr>
<tr>
<th scope="row">Задача:</th>
<td>Научиться запускать свои проекты используя <em>Express Application Generator</em>.</td>
</tr>
</tbody>
</table>
<h2 id="Обзор">Обзор</h2>
<p>В этой статье показано, как создать каркас сайта с помощью средства <a href="https://expressjs.com/en/starter/generator.html">Express Application Generator</a>. Каркас затем можно будет заполнить с помощью путей сайта, шаблонов/представлений и обращений к базе данных. Мы используем это средство для создания основы нашего <a>сайта Local Library</a>. К основе будет добавлен код, необходимый сайту. Создание каркаса чрезвычайно просто -- требуется только вызвать генератор в командной строке, указав имя нового проекта, дополнительно можно указать также движок шаблона сайта и генератор CSS.</p>
<p>Далее показано, как вызвать генератор приложений, и даётся небольшое пояснение различных вариантов представлений и CSS. Мы поясним структуру каркаса веб-сайта. В конце мы покажем, как запустить веб-сайт, чтобы убедиться, что он работает.</p>
<div class="note">
<p><span style="line-height: 1.5;"><strong>Замечание</strong>: </span><em>Express Application Generator</em> — не единственный генератор Express-приложений, и созданный проект --не единственный жизнеспособный способ организации ваших файлов и каталогов. Однако созданный сайт имеет модульную структуру, которую легко понять и расширить. О <em>минимальном</em> Express приложении смотрите <a href="https://expressjs.com/en/starter/hello-world.html">Hello world example</a> в документации Express.</p>
</div>
<h2 id="Применение_генератора_приложений">Применение генератора приложений</h2>
<p>Вы уже должны были установить <code>express-generator</code>, читая статью <a>установка среды разработки Node</a>. Напомним, что генератор установлен с помощью менеджера пакетов NPM, при выполнении команды:</p>
<pre class="brush: bash notranslate"><code>npm install express-generator -g</code>
</pre>
<p><code>E</code><code>xpress-generator </code>имеет ряд параметров, которые можно увидеть, выполнив команду express --help (или express -h):</p>
<pre class="brush: bash notranslate">> express --help
Usage: express [options] [dir]
Options:
-h, --help output usage information (информация по применению)
--version output the version number (номер версии express)
-e, --ejs add ejs engine support (добавить поддержку движка ejs)
--pug add pug engine support (добавить поддержку движка pug)
--hbs add handlebars engine support (добавить поддержку движка handlebar)
-H, --hogan add hogan.js engine support (добавить поддержку движка hogan.js)
-v, --view <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
(добавить поддержку движков представлений. По умолчанию - jade)
-c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
(добавить поддержку движков стилей, по умолчанию - простой CSS)
--git add .gitignore (добавить поддержку .gitignore)
-f, --force force on non-empty directory (работать в каталоге с файлами)
</pre>
<p>Команда <code>express</code> создаст проект в <em>текущем</em> каталоге с использованием (устаревшего) движка представления <em>Jade</em> и обычного CSS. Если указать <font face="Courier New, monospace">express </font><font face="Courier New, monospace">name</font>, проект будет создан в подкаталоге name текущего каталога. </p>
<pre class="brush: bash notranslate"><code>express</code></pre>
<p>Можно выбрать движок представления (шаблон), используя --<code>view; </code><code><font face="Times New Roman, serif">параметр</font></code><code> --</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><em>Express-generator</em><em> </em>даёт возможность сконфигурировать несколько популярных движков, включая <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. Экспресс сразу после установки может поддерживать большое количество и других шаблонизаторов.</p>
<div class="note">
<p><strong>Заметка:</strong> При желании использовать шаблонизатор, который не поддерживается генератором, просмотрите документацию <a href="https://expressjs.com/en/guide/using-template-engines.html"><font color="#3d7e9a"><font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><font size="3">Using template engines with Express</font></font></font></a><font color="#333333"><font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><font size="3"> </font></font></font> и документацию для нужного шаблонизатора.</p>
</div>
<p>Как правило, следует выбрать шаблонизатор, который имеет весь необходимый вам функционал и обеспечивает вам высокую производительность - так же, как вы выбираете любой другой компонент! Некоторые критерии для сравнения шаблонизаторов:</p>
<ul>
<li>Время до получения результата — если ваша команда уже имела дело с шаблонизатором, то, скорее всего, продуктивнее будет использовать этот шаблонизатор. Если нет, тогда следует учесть все относительные сложности изучения кандидатов в шаблонизаторы.</li>
<li>Популярность и активность — проверьте популярность движка, возможно, у него есть активное сообщество. Очень важно иметь поддержку для движка, если у вас возникнут проблемы в течении жизни веб-сайта.</li>
<li>Стиль — некоторые шаблонизаторы используют особую разметку для отображения вставленного контента внутри "обычного" HTML, а другие строят HTML, используя специальный синтаксис (например, используя отступы или блочные имена).</li>
<li>Производительность и время интерпретации.</li>
<li>Особенности — следует выбирать движок с учётом таких особенностей:
<ul>
<li>Наследование макета: позволяет определить базовый шаблон и затем наследовать только те части, которые отличаются для конкретной страницы. Это, как правило, лучший подход, чем создание шаблонов путём включения нескольких необходимых компонентов или создания шаблона с нуля каждый раз.</li>
<li>Поддержка «Include»: позволяет создавать шаблоны, включая другие шаблоны.</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-generator "из коробки".</p>
<h3 id="Какие_шаблонизаторы_CSS_следует_использовать">Какие шаблонизаторы CSS следует использовать?</h3>
<p><em>Express Application Generator</em> позволяет создавать проекты, настроенные для применения шаблонизаторов 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>простой<strong> </strong>CSS имеет некоторые ограничения, затрудняющие выполнение задач. Шаблонизаторы CSS позволяют использовать более эффективный подход для создании таблиц стилей CSS, но требуют компиляции файлов таблиц стилей в стандартный CSS для применения в браузере.</p>
</div>
<p>Как и в случае с шаблонизаторами сайта, следует применять шаблонизатор, обеспечивающий высокую производительность работы. В этом проекте мы используем обычный CSS (по умолчанию), поскольку простота наших требований к CSS не оправдает применение чего-то более сложного.</p>
<h3 id="Какую_базу_данных_следует_использовать">Какую базу данных следует использовать?</h3>
<p>Сгенерированный код не использует и не содержит в себе какой-либо базы данных. <em>Express</em> может использовать любой движок <a href="https://expressjs.com/en/guide/database-integration.html">базы данных</a>, который поддерживается <em>Node</em> (<em>Express</em> не предъявляет каких-либо особых требований к базе данных).</p>
<p>Мы обсудим взаимодействие с базой данных в следующей статье.</p>
<h2 id="Создание_проекта">Создание проекта</h2>
<p>Разрабатывая пример - приложение <em>Local Library, </em>мы построим проект с именем <em>express-locallibrary-tutorial. </em>Используем библиотеку шаблонов Pug, а движок CSS применять не будем.</p>
<p>Выберем место для нового проекта — каталог <font face="Courier New, monospace">express-locallibrary-tutorial - </font><font face="Times New Roman, serif">и выполним</font><font face="Courier New, monospace"> </font>команду:</p>
<pre class="brush: bash notranslate">express express-locallibrary-tutorial --view=pug
</pre>
<p>Будет создан каталог <font face="Courier New, monospace">express-locallibrary-tutorial </font><font face="Times New Roman, serif">и выведен список созданных внутри каталога проектных файлов</font>.</p>
<pre class="brush: bash notranslate"> create : express-locallibrary-tutorial
create : express-locallibrary-tutorial/package.json
create : express-locallibrary-tutorial/app.js
create : express-locallibrary-tutorial/public/images
create : express-locallibrary-tutorial/public
create : express-locallibrary-tutorial/public/stylesheets
create : express-locallibrary-tutorial/public/stylesheets/style.css
create : express-locallibrary-tutorial/public/javascripts
create : express-locallibrary-tutorial/routes
create : express-locallibrary-tutorial/routes/index.js
create : express-locallibrary-tutorial/routes/users.js
create : express-locallibrary-tutorial/views
create : express-locallibrary-tutorial/views/index.pug
create : express-locallibrary-tutorial/views/layout.pug
create : express-locallibrary-tutorial/views/error.pug
create : express-locallibrary-tutorial/bin
create : express-locallibrary-tutorial/bin/www
install dependencies:
> cd express-locallibrary-tutorial && npm install
run the app:
> SET DEBUG=express-locallibrary-tutorial:* & npm start</pre>
<p>После списка файлов генератор выведет инструкции для установки зависимостей (указанных в файле <strong>package.json</strong>) и запуска приложения (инструкции предназначены для Windows; для Linux/Mac OS X они могут слегка отличаться).</p>
<h2 id="Запускаем_каркас_сайта">Запускаем каркас сайта</h2>
<p>Сейчас у нас есть готовый каркас проекта. Сайт пока ничего не делает, но его стоит запустить, чтобы убедиться в его работоспособности.</p>
<ol>
<li>Прежде всего установим зависимости (команда <code>install</code> запросит все пакеты зависимостей, указанные в файле<strong> package.json</strong>).
<pre class="brush: bash notranslate">cd express-locallibrary-tutorial
npm install</pre>
</li>
<li>Затем запустим приложение.
<ul>
<li>В Windows используйте команду:
<pre class="brush: bash notranslate">SET DEBUG=express-locallibrary-tutorial:* & npm start</pre>
</li>
<li>В Mac OS X или Linux используйте команду:
<pre class="brush: bash notranslate">DEBUG=express-locallibrary-tutorial:* npm start
</pre>
</li>
</ul>
</li>
<li>Откроем <a href="http://localhost:3000/">http://localhost:3000/</a> в браузере. Мы должны увидеть такую страницу:</li>
</ol>
<p><img alt="Browser for default Express app generator website" src="https://mdn.mozillademos.org/files/14375/ExpressGeneratorSkeletonWebsite.png" style="display: block; height: 403px; margin: 0px auto; width: 576px;"></p>
<p>У нас получилось веб-приложение на базе Express, работающее по адресу <em>localhost:3000</em>.</p>
<div class="note">
<p><strong>Заметка:</strong> Можно также запустить приложение командой <code>npm start</code>. Переменная DEBUG, указанная в примере, включает логирование в консоль для дальнейшей отладки. Так, при посещении страницы веб-приложения, вы увидите похожий вывод в консоль:</p>
<pre class="brush: bash notranslate">>SET DEBUG=express-locallibrary-tutorial:* & npm start
> express-locallibrary-tutorial@0.0.0 start D:\express-locallibrary-tutorial
> node ./bin/www
express-locallibrary-tutorial:server Listening on port 3000 +0ms
GET / 200 288.474 ms - 170
GET /stylesheets/style.css 200 5.799 ms - 111
GET /favicon.ico 404 34.134 ms - 1335</pre>
</div>
<h2 id="Обеспечиваем_перезапуск_сервера_при_изменении_файлов">Обеспечиваем<br>
перезапуск сервера при изменении файлов</h2>
<p>Любые изменения, внесённые на веб-сайт Express, не будут отображаться до перезапуска сервера. Остановка (Ctrl-C) и перезапуск сервера каждый раз после внесения изменений быстро становится раздражающей, поэтому стоит автоматизировать перезапуск.</p>
<p>Одно из самых простых средств для этого --<br>
<a href="https://github.com/remy/nodemon">nodemon</a>. Его обычно устанавливают глобально (так как это "инструмент"), но сейчас мы установим его и будем применять локально как зависимость разработки, так что любые разработчики проекта получат его автоматически при установке приложения. Выполним следующую команду (предполагаем, что мы находимся в корневом каталоге):</p>
<pre class="brush: bash notranslate">npm install --save-dev nodemon</pre>
<p>Если вы предпочитаете установить nodemon глобально, не только для этого проекта, надо выполнить команду</p>
<pre class="notranslate"><code><font color="#333333"><font face="Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace"><font size="3">npm install -g nodemon</font></font></font></code></pre>
<p>В файле <strong>package.json </strong>проекта появится новый раздел с этой зависимостью (на вашей машине номер версии nodemon может быть другим) :</p>
<pre class="brush: json notranslate"> "devDependencies": {
"nodemon": "^1.11.0"
}
</pre>
<p>Поскольку nodemon не установлен глобально, его нельзя запустить из командной строки (пока мы не добавим его в путь), но его можно вызвать из сценария NPM, так как NPM знает все об установленных пакетах. Раздел <code>scripts</code> в файле package.json исходно будет содержать одну строку, которая начинается с <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>Теперь можно запустить сервер почти так же, как и ранее, но командой npm run devstart:</p>
<ul>
<li>В Windows:</li>
</ul>
<pre class="brush: bash notranslate">SET DEBUG=express-locallibrary-tutorial:* & npm <strong>run devstart</strong></pre>
<ul>
<li>Для macOS или Linux:</li>
</ul>
<pre class="notranslate"><code>DEBUG=express-locallibrary-tutorial:* npm <strong>run devstart</strong></code></pre>
<div class="note">
<p><strong>Заметка:</strong> Сейчас после изменения любого файла проекта сервер будет перезапускаться (или можно самостоятельно перезапустить его, введя <code>rs</code> в командной строке). Вам всё равно придётся обновить страницу в браузере .</p>
<p>Теперь мы должны выполнять команду "<code>npm run </code><em><scriptname></em>" а не просто <code>npm start</code>, поскольку "start", это, по сути, команда NPM, сопоставленная сценарию в файле package.json. Можно заменить команду в сценарии "start", но, так как мы хотим использовать nodemon только во время разработки, разумно создать новую команду сценария.</p>
</div>
<h2 id="Созданный_проект">Созданный проект</h2>
<p>Давайте посмотрим на созданный проект.</p>
<h3 id="Структура_каталогов">Структура каталогов</h3>
<p>После установки зависимостей проект имеет такую структуру файлов (файлы - это элементы <strong>без </strong>префикса"/"). Файл <strong>package.json</strong> определяет имя файла с приложением, сценарии запуска, зависимости и др. Сценарий запуска задаёт точку входа приложения, у нас -- файл JavaScript <strong>/bin/www</strong>. Этот файл настраивает некоторые обработчики ошибок приложения, а затем загружает <strong>app.js </strong>для выполнения остальной работы. Пути приложения хранятся в отдельных модулях каталога <strong>routes/</strong>. Шаблоны хранятся в каталоге /<strong>views</strong>.</p>
<pre class="notranslate">/express-locallibrary-tutorial
<strong>app.js</strong>
/bin
<strong>www</strong>
<strong>package.json</strong>
/node_modules
[about 4,500 subdirectories and files]
/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>Далее файлы описаны более подробно.</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": {
"body-parser": "~1.15.2",
"cookie-parser": "~1.4.3",
"debug": "~2.2.0",
<strong> "express": "~4.14.0",</strong>
"morgan": "~1.7.0",
<strong> "pug": "~2.0.0-beta6",</strong>
"serve-favicon": "~2.3.0"
},
"devDependencies": {
"nodemon": "^1.11.0"
}
}</pre>
<p>Зависимости включают пакет express и пакет для выбранного движка представления (pug). Кроме того, указаны пакеты, полезные во многих веб-приложениях:</p>
<ul>
<li><a href="https://www.npmjs.com/package/body-parser">body-parser</a>: -- анализирует часть тела входящего запроса HTTP и облегчает извлечение из него различных частей. Например, мы можно читать <code>POST-</code>параметры.</li>
<li><a href="https://www.npmjs.com/package/cookie-parser">cookie-parser</a>: разбирает заголовок и заполняет <code>req.cookies</code> (по сути, даёт удобный метод для доступа к информации cookie).</li>
<li><a href="https://www.npmjs.com/package/debug">debug</a>: небольшой отладчик, работающий по образцу методики отладки ядра node.</li>
<li><a href="https://www.npmjs.com/package/morgan">morgan</a>: средство логирования запросов HTTP для node.</li>
<li><a href="https://www.npmjs.com/package/serve-favicon">serve-favicon</a>: средство обработки <a href="https://en.wikipedia.org/wiki/Favicon">favicon</a> (значка, используемого для представления сайта на вкладках браузера, закладках и т. д).</li>
</ul>
<p>Раздел "scripts" определяет скрипт" start", выполняемый при запуске сервера командой <code>npm start</code>. Можно видеть, что самом деле выполняется команда node <strong>./bin/www</strong>. Кроме того, определяется script "<em>devstart</em>", который вызывается командой <code>npm run devstart</code>. Запускается тот же файл <strong>./bin/www</strong> ,но командой <em>nodemon</em> вместо <em>node</em>.</p>
<pre class="notranslate"><code>"scripts": {
"start": "node ./bin/www",
"devstart": "nodemon ./bin/www"
},</code></pre>
<h3 id="Файл_www">Файл www</h3>
<p>Файл <strong>/bin/www</strong> – это входная точка приложения. Сначала в файле создаётся объект основного приложения, расположенного в app.js — выполняется app=<code>require(./</code><code>app</code><code>).</code></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>указан относительный путь, а расширение файла по умолчанию (.js) опущено.</p>
</div>
<p>Оставшаяся часть кода настраивает порт сервера node для HTTP (определён в переменной среды или 3000, если не определён), и начинает обработку и протоколирование соединений и ошибок сервера. Сейчас вам не требуется дополнительных сведений о коде (все в этом файле шаблонно), но, при желании, его можно посмотреть.</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>Именно этот экспортированный объект использован в рассмотренном ранее файле www.</p>
<p>Рассмотрим детали файла app.js. Сначала при помощи require(...) выполняется импорт некоторых полезных библиотек node: <em>express,</em> s<em>erve-favicon</em>, <em>morgan</em>, <em>cookie-parse, body-parser </em>(они ранее были загружены для нашего приложения командой npm install), а также path из основной библиотеки node (применяется для разбора путей каталогов и файлов).</p>
<pre class="brush: js notranslate">var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
</pre>
<p>Затем require запрашивает модули из каталога путей route. Эти модули и файлы содержат код для обработки конкретного набора соответствующих путей (URL маршрутов). Если мы расширим каркас приложения, например, чтобы получить список книг библиотеки, нам следует добавить новый файл для обработки пути, связанного с книгами.</p>
<pre class="brush: js notranslate">var index = require('./routes/index');
var users = require('./routes/users');
</pre>
<div class="note">
<p><strong>Заметка:</strong> Здесь мы только импортируем модули. В действительности эти пути ещё не используются — это произойдёт в файле несколько позже.</p>
</div>
<p>Далее, импортированные модули express применяются для создания объекта app, который потом устанавливает движки-шаблоны представления. Установка движков состоит их двух частей. В первой мы задаём значение 'view', указывая папку, в которой будут размещаться шаблоны (у нас это /views). Во второй мы задаём значение движка 'view engine', указывая на библиотеку шаблона (у нас — "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>Следующие строки вызывают app.use(...), чтобы добавить промежуточные (middleware) библиотеки в цепочку обработки запросов. Кроме сторонних библиотек, импортированных ранее, используем библиотеку Express.static, что позволит обрабатывать статические файлы из папки <strong>/public </strong>корня проекта.</p>
<pre class="brush: js notranslate">// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.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('/', index);
app.use('/users', users);
</pre>
<div class="note">
<p><strong>Заметка:</strong> . пути, указанные выше ('/' и '<code>/users'</code>) рассматриваются как префиксы путей, определённых в импортированных файлах. Так, например, если импортированный модуль users определяет путь для /profile, для доступа следует указать /users/profile. Мы поговорим подробнее о путях в последующей статье.</p>
</div>
<p>Последняя в файле промежуточная библиотека добавляет методы обработки ошибок и ответов 404 от HTTP.</p>
<pre class="brush: js notranslate">// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// 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');
});
</pre>
<p>Объект app приложения Express теперь полностью настроен. Остался последний шаг - добавить его к экспортируемым элементам модуля (это позволит импортировать его в файле <strong>/bin/www</strong>).</p>
<pre class="brush: js notranslate">module.exports = app;</pre>
<h3 id="Пути_Routes">Пути (Routes)</h3>
<p>Файл путей /routes/users.js приведён ниже (файлы путей имеют сходную структуру, поэтому нет необходимости приводить также index.js). Сначала загружается модуль Express, затем он используется для получения объекта express.Router. После этого для этого объекта задаётся путь, и, наконец, объект-роутер экспортируется из модуля (именно это позволяет импортировать файл в app.js):.</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 GET-запрос корректного вида. Образец для сопоставления пути задаётся при импорте модуля -- ('<code>/users</code>') плюс что-то, определяемое в этом файле ('<code>/</code>'). Иными словами, этот путь будет использован, когда получен URL-запрос <code>/users/</code>.</p>
<div class="note">
<p><strong>Совет:</strong> запустите сервер и задайте в браузере URL <a href="http://localhost:3000/users/">http://localhost:3000/users/</a>. Вы должны увидеть<strong> </strong>сообщение: 'respond with a resource'.</p>
</div>
<p>Стоит отметить, что колбэк-функция имеет третий аргумент - '<code>next</code>', т. е. является не простой колбэк-функцией, а колбэк-функцией промежуточного модуля. Пока третий аргумент не используется, но будет полезен в дальнейшем, если мы захотим создать несколько обработчиков пути <code><font color="#333333"><font face="consolas, Liberation Mono, courier, monospace"><font size="3">'/'</font></font></font></code>.</p>
<h3 id="Представления_шаблоны">Представления (шаблоны)</h3>
<p>Файлы преставлений (шаблонов) хранятся в каталоге <strong><font color="#333333"><font face="Arial, x-locale-body, sans-serif"><font size="3">/views </font></font></font></strong><font color="#333333"><font face="Times New Roman, serif"><font size="3">(это указано в </font></font><font face="Courier New, monospace"><font size="3">app.js</font></font><font face="Times New Roman, serif"><font size="3">) и имеют расширение</font></font></font><strong><font color="#333333"><font face="Times New Roman, serif"><font size="3"> </font></font></font></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> (приводится ниже) можно увидеть, что роут отвечает, используя шаблон "index" с переданным значением переменной "title" из шаблона.</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>). О синтаксисе мы поговорим позже. Сейчас важно знать, что переменная title со значением 'Express' помещена в определённое место шаблона.</p>
<pre class="notranslate">extends layout
block content
h1= title
p Welcome to #{title}
</pre>
<h2 id="Мини-тест">Мини-тест</h2>
<p>Создайте новый путь в <strong>/routes/users.js</strong>, чтобы выводить текст <strong>"</strong><em>You're so cool" </em>или<em> </em><em>"</em><em>Ну, вы крутой!</em><em>" </em>по URL<em> </em><code>/users/cool/</code><em>. </em>Проверьте его, запустив сервер и посетив в браузере <em><a href="http://localhost:3000/users/cool/">http://localhost:3000/users/cool/</a>.</em></p>
<ul>
</ul>
<h2 id="Итоги">Итоги</h2>
<p>Сейчас создан каркас проекта <a>Local Library</a>. Мы проверили, что он запускается с использованием Node. Но главное, что вы поняли структуру проекта, и знаете, где и как добавить пути и представления для нашей локальной библиотеки.</p>
<p lang="ru-RU">Далее мы изменим каркас, чтобы он работал как библиотечный веб-сайт</p>
<h2 id="Смотрите_также">Смотрите также</h2>
<ul>
<li><a href="https://expressjs.com/en/starter/generator.html">Express application generator</a> (документация Express)</li>
<li><a href="https://expressjs.com/en/guide/using-template-engines.html">Using template engi nes with 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>
|