Учебник Express часть 2: Создание скелета сайта

Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Эта вторая статья в нашем учебнике Express показывает, как вы можете создать «скелет» проекта веб-сайта, который затем можно будет заполнить с помощью маршрутов сайта, шаблонов/представлений и вызовов базы данных.

Необходимые знания: Установить среду разработки Node. Просмотреть обзорно учебник Express.
Задача: Научиться запускать свои проекты используя Express Application Generator.

Обзор

В этой статье показано как вы можете создать "скелет" сайта с помощью инструмента Express Application Generator, который затем можно будет заполнить с помощью маршрутов сайта, шаблонов/представлений и вызовов базы данных. В этом случае мы будем использовать инструмент для создания основы для нашего сайта Local Library, к которому мы добавим весь другой код необходимый сайту. Процесс чрезвычайно прост, требуется только, чтобы вы вызвали генератор в командной строке с новым именем проекта, опционально также определяя механизм шаблона сайта и генератор CSS.

В следующих разделах показано, как вызвать генератор приложений, и даётся небольшое объяснение различных вариантов просмотра/CSS. Мы также объясним, как структурирован скелет веб-сайта. В конце мы покажем, как вы можете запустить веб-сайт, чтобы убедиться, что он работает.

Замечание: Express Application Generator генератор не только для Express приложений, и генерирование проекта не единственный способ организации для ваших файлов и директорий. Однако созданный сайт имеет модульную структуру, которую легко расширить и понять. Для информации о минимальном Express приложении, смотрите Hello world example (документация Express).

Использование генератора приложений

Вы уже должны были устанавливать генератор в статье установка среды разработки Node. Для быстрого напоминания, вы установили генератор используя пакетный менеджер NPM, следующим образом:

npm install express-generator -g

Генератор имеет несколько параметров, которые вы можете просмотреть в командной строке с помощью команды --help (или -h):

> express --help

  Usage: express [options] [dir]

  Options:

    -h, --help           output usage information
        --version        output the version number
    -e, --ejs            add ejs engine support
        --pug            add pug engine support
        --hbs            add handlebars engine support
    -H, --hogan          add hogan.js engine support
    -v, --view <engine>  add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
    -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
        --git            add .gitignore
    -f, --force          force on non-empty directory

Вы можете просто указать express для создания проекта в текущем каталоге с использованием механизма просмотра Jade и обычного CSS (если вы укажете имя каталога, тогда проект будет создан в подпапке с этим именем).

express

Вы также можете выбрать механизм просмотра (шаблона), используя --view и/или механизм генерации CSS с помощью --css.

Заметка: Другие опции для выбора шаблонизатора (такие как --hogan, --ejs, --hbs и пр.) устарели. Используйте --view (или -v)!

Какой шаблонизатор я могу использовать?

Экспресс генератор приложений позволяет вам сконфигурировать несколько популярных движков, включая EJS, Hbs, Pug (Jade), Twig, и Vash, тем не менее Jade выбран поумолчанию. Экспресс сам по себе может поддерживать большое количество шаблонизаторов из коробки.

Заметка: Если вы хотите использовать шаблонизатор, который не поддерживается генератором, тогда смотрите Использование шаблонных движков с Экспресс (Экспресс документация) и документацию для вашего шабонизатора.

Одним словом вы должны выбрать шаблонизатор, который имеет весь необходимый вам функционал и позволяет вам стать производительным как можно быстрее - другими словами, так же как вы выбираете любой другой компонент! Некоторые критерии для сравнения шаблонизаторов:

  • Время до производительности — Если ваша команда уже имела дело с шаблонизатором, в таком случае скорей всего продуктивнее будет использовать этот шаблонизатор. Если нет, тогда вам нужно рассмотреть все относительные сложности изучения для кандидатов в шаблонизаторы.
  • Популярность и активность — Проверьте популярность движка, возможно у него есть активное сообщество. Это очень важно иметь поддержку для движка, когда у вас возникают проблемы в течении жизни вебсайта.
  • Стиль — Некоторые шаблонизаторы используют специфическую разметку для отображения вставленного контента внутри "обычного" HTML, пока другие строят  HTML используя разный синтаксис (например, используя отступы или блочные имена).
  • Производительность/время интерпретации.
  • Особенности — вы должны выбирать движок  по наличию следующих особенностей:
    • Наследование макета: позволяет вам определить базовый шаблон и затем наследовать только те части, которые отличаются для конкретной страницы. Это, как правило, лучший подход, чем создание шаблонов путём включения нескольких необходимых компонентов или создания шаблона с нуля каждый раз.
    • Поддержка «Include»: позволяет создавать шаблоны, включая другие шаблоны.
    • Краткий синтаксис управления переменными и циклами.
    • Возможность фильтровать значения переменных на уровне шаблона (например, делать переменные в верхнем регистре или форматировать значение даты).
    • Возможность создавать выходные форматы, отличные от HTML (например, JSON или XML).
    • Поддержка асинхронных операций и потоковой передачи. Может использоваться как на клиенте, так и на сервере. Если на клиенте можно использовать шаблонный движок, это позволяет использовать данные и выполнять всю или большую часть рендеринга на стороне клиента.

Совет: В интернете множество ресурсов, которые могут оказать помощь в сравнении различных опций!

Для этого проекта мы будем использовать Pug в качестве шаблонизатора (в прошлом назывался Jade), так как это один из наиболее популярных Express/JavaScript шаблонизаторов, который поддерживается генератором без дополнительных настроек.

Какие шаблонизаторы CSS я могу использовать?

Express Application Generator позволяет вам создавать проекты, сконфигурированные для использования шаблонизаторов CSS: LESS, SASS, Compass, Stylus.

Заметка: CSS имеет некоторые ограничения, которые затрудняют выполнение задач. Шаблонизаторы CSS позволяют вам использовать более эффективный синтаксис для создании таблиц стилей CSS, после чего компилирует файлы шаблонизатора таблиц стилей в стандартный CSS для его восприятия браузером.

Как и в случае с шаблонизатором сайта вы должны использовать шаблонизатор, позволяющий вам и вашей команде работать более продуктивно. Для этого проекта мы будем использовать обычный CSS (по умолчанию), поскольку наши требования к CSS недостаточно сложны, чтобы оправдать использование чего-либо еще.

Какую базу данных я могу использовать?

Сгенерированный код не использует/включает в себя какую-либо базу данных. Express может использовать любой механизм взаимподействия с базой данных, который поддерживается Node (Express не предъявляет каких-либо специфичных требований к базе данных).

Мы будем обсуждать взаимодействие с базой данных в следующей статье.

Создание проекта

For the sample Local Library app we're going to build, we'll create a project named express-locallibrary-tutorial using the Pug template library and no CSS stylesheet engine.

Для начала перейдите в в директорию, которая будем использована для создания нового проекта и запустите Express Application Generator командой, указанной нижеin the command prompt as shown:

express express-locallibrary-tutorial --view=pug

Генератор создаст (и выведет списоком) проектные файлы.

   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

После списка созданных объектов генератор выведет инструкции для установки зависимостей (которые указаны в файле package.json) и запуска приложения (указанные выше инструкции предназначены для Windows; для Linux/Mac OS X они могут слегка отличаться).

Запускаем скелет сайта

На данный момент у нас есть готовый скелет проект. Сайт на самом деле пока ничего не делает, но его стоит запустить для демонстрации его работы.

  1. Для начала установите зависимости (команда install запросит все пакеты зависимостей, указанных в файле package.json).
    cd express-locallibrary-tutorial
    npm install
  2. Затем запустите приложение.
    • В Windows используйте эту команду:
      SET DEBUG=express-locallibrary-tutorial:* & npm start
    • В Mac OS X или Linux, используйте эту комманду:
      DEBUG=express-locallibrary-tutorial:* npm start
      
  3. Откройте http://localhost:3000/ в вашем браузере для получения доступа к сайту.

Вы можете увидеть страницу, выглядящую так:

Browser for default Express app generator website

У вас есть веб-приложение на базе Express, работающее по адресу localhost:3000.

Заметка: Вы можете также запустить приложение с помощью команды npm start. Переменная DEBUG, указанная в примере, включает логгирование в консоль для дальнейшей отладки. К примеру, при посещении страницы веб-приложения, вы увидите похожий вывод в консоль:

>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

Включить перезапуск сервера при изменении файла

Любые изменения, внесенные на веб-сайт Express, в настоящее время не отображаются до перезапуска сервера. Это быстро становится очень раздражающим, чтобы остановить и перезапустить сервер каждый раз, когда вы вносите изменения, поэтому стоит потратить время, чтобы автоматизировать перезапуск сервера, когда это необходимо.

Одним из самых простых таких инструментов для этой цели является nodemon. Его обычно устанавливают глобально (поскольку это" инструмент"), но  здесь мы будем устанавливать и использовать его локально как главный разработчик, так что любые разработчики, работающие с проектом, получают его автоматически при установке приложения. Используйте следующую программу в корневом каталоге для каркаса проекта:

npm install --save-dev nodemon

Если вы откроете в вашем проекте файл package.json,  вы увидете новый раздел с этой записью:

  "devDependencies": {
    "nodemon": "^1.11.0"
  }

Поскольку инструмент не установлен глобально, мы не можем запустить его из командной строки (если мы не добавим его в путь) но мы можем вызвать его из сценария NPM, потому что NPM знает все об установленных пакетах. Найдите раздел  scripts в вашем package.json. Вначале он будет содержать одну строку, которая начинается с  "start".Обновить его, поставив запятую в конце строки, и добавьте строку "devstart"  показанную ниже:

  "scripts": {
    "start": "node ./bin/www",
    "devstart": "nodemon ./bin/www"
  },

Теперь мы можем запустить сервер почти точно так же, как и ранее, но с указанной командой devstart:

  • В Windows, используя команду:
SET DEBUG=express-locallibrary-tutorial:* & npm run devstart
  • Для macOS или Linux используя эту команду:
DEBUG=express-locallibrary-tutorial:* npm run devstart

Заметка: Теперь если вы будете редактировать любой файл в проекте сервер будет перезапускаться(или вы можете перезапустить его, введя  rs в командной строке в любое время). Вам все равно придется обновить, чтобы обновить страницу.

Теперь мы должны вызвать  "npm run <scriptname>" а не просто  npm start, поскольку "start" на самом деле является командой NPM, сопоставленной с именованным сценарием. Мы могли бы заменить команду в сценарии запуска, но мы хотим использовать nodemon только во время разработки, поэтому имеет смысл создать новую команду сценария.

Созданный проект

Давайте теперь посмотрим на проект, который мы только что создали.

Структура директорий

Созданный проект, после установки зависимостей, имеет следующую структуру файлов (файлы-это элементы без префикса"/"). Файл package.json определяет зависимости приложения и другую информацию. Так же он определяет сценарий запуска, который будет вызывать точку входа приложения, файл JavaScript /bin/www. Он настраивает некоторые обработчики ошибок приложения, а затем загружает  app.js, чтобы сделать остальную часть работы. Маршруты приложения хранятся в отдельных модулях в каталоге routes/.  Шаблоны хранятся в папке /views.

/express-locallibrary-tutorial
    app.js
    /bin
        www
    package.json
    /node_modules
        [about 4,500 subdirectories and files]
    /public
        /images
        /javascripts
        /stylesheets
            style.css
    /routes
        index.js
        users.js
    /views
        error.pug
        index.pug
        layout.pug
    

В следующих разделах файлы описаны более подробно.

package.json

Файл package.json описывает зависимости приложения и другую информацию:

{
  "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",
    "express": "~4.14.0",
    "morgan": "~1.7.0",
    "pug": "~2.0.0-beta6",
    "serve-favicon": "~2.3.0"
  },
  "devDependencies": {
    "nodemon": "^1.11.0"
  }
}

Зависимости включают пакет express и пакет для выбранного механизма просмотра (pug). Кроме того, у нас есть следующие пакеты, которые полезны во многих веб-приложениях:

  • body-parser: Это анализирует часть тела входящего запроса HTTP и облегчает извлечение различных частей содержащейся информации. Например , мы можем читать POST параметры.
  • cookie-parser: Парсить заголовок и заполнения req.cookies (по существу обеспечивает удобный метод для доступа к информации cookie).
  • debug: Маленькая утилита для отладки node, смоделированная после метода отладки ядра node.
  • morgan: Запрос HTTP middleware для node.
  • serve-favicon: Node middleware для обработки favicon (это значок, используемый для представления сайта внутри вкладки браузера, закладок и т. д).

Раздел скрипты определяет скрипт" start", который мы вызываем при вызове запуска сервера npm start. Из определения скрипта вы можете видеть, что это на самом деле запускает файл JavaScript ./bin/www с node. Так же он определяет script"devstart" , который мы we вызываем при npm run devstart instead. Все начинается с того же файла ./bin/www ,но с nodemon вместо node.

"scripts": {
    "start": "node ./bin/www",
    "devstart": "nodemon ./bin/www"
  },

www file

Этот файл /bin/www отправная точка приложения! Первым делом он выполняет require() "реальная" отправная точка (app.js, в корне проекта) она настраивает и вызвывает  объект приложения  express().

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');

Заметка: require() глобальная функция node, используемая для импорта модулей в текущий файл.. Здесь мы указали модуль app.js использующий относительный путь и пропускающий необязательное(.js) расширение файла.

Оставшаяся часть кода настраивает сервер node HTTP с app установленной на определенный порт (определенный в переменной среды или 3000, если переменная не определена), и начинает прослушивание и ошибки сервера отчетов и соединения. На данный момент вам не нужно ничего знать о коде (все в этом файле "boilerplate"), но вы можете посмотреть его если вам инересно.

app.js

Этот файл создает объект приложения  express(с именемapp, по соглашению), настраивает приложение с различными настройками и промежуточным ПО, а затем экспортирует приложение из модуля. В приведенном ниже коде показаны только те части файла, которые создают и экспортируют объект приложения:

var express = require('express');
var app = express();
...
module.exports = app;

Back in the www entry point file above, it is this module.exports object that is supplied to the caller when this file is imported.

Lets work through the app.js file in detail. First we import some useful node libraries into the file using require(), including express, serve-favicon, morgan, cookie-parser and body-parser that we previously downloaded for our application using NPM; and path, which is a core Node library for parsing file and directory paths.

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');

Then we require() modules from our routes directory. These modules/files contain code for handling particular sets of related "routes" (URL paths). When we extend the skeleton application, for example to list all books in the library, we will add a new file for dealing with book-related routes.

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

Note: At this point we have just imported the module; we haven't actually used its routes yet (this happens just a little bit further down the file).

Next we create the app object using our imported express module, and then use it to set up the view (template) engine. There are two parts to setting up the engine. First we set the 'views' value to specify the folder where the templates will be stored (in this case the sub folder /views). Then we set the 'view engine' value to specify the template library (in this case "pug").

var app = express();

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

The next set of functions call app.use() to add the middleware libraries into the request handling chain. In addition to the 3rd party libraries we imported previously, we use the Express.static middleware to get Express to serve all the static files in the directory /public in the project root.

// 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());
app.use(express.static(path.join(__dirname, 'public')));

Now that all the other middleware is set up, we add our (previously imported) route-handling code to the request handling chain. The imported code will define particular routes for the different parts of the site:

app.use('/', index);
app.use('/users', users);

Note: The paths specified above ('/' and '/users') are treated as a prefix to routes defined in the imported files. So for example if the imported users module defines a route for /profile, you would access that route at /users/profile. We'll talk more about routes in a later article.

The last middleware in the file adds handler methods for errors and HTTP 404 responses.

// 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');
});

The Express application object (app) is now fully configured. The last step is to add it to the module exports (this is what allows it to be imported by /bin/www).

module.exports = app;

Routes

The route file /routes/users.js is shown below (route files share a similar structure, so we don't need to also show index.js). First it loads the express module, and uses it to get an express.Router object. Then it specifies a route on that object, and lastly exports the router from the module (this is what allows the file to be imported into app.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;

The route defines a callback that will be invoked whenever an HTTP GET request with the correct pattern is detected. The matching pattern is the route specified when the module is imported ('/users') plus whatever is defined in this file ('/'). In other words, this route will be used when an URL of /users/ is received.

Tip: Try this out by running the server with node and visiting the URL in your browser: http://localhost:3000/users/. You should see a message: 'respond with a resource'.

One thing of interest above is that the callback function has the third argument 'next', and is hence a middleware function rather than a simple route callback. While the code doesn't currently use the next argument, it may be useful in the future if you add want to add multiple route handlers to the '/' route path.

Views (templates)

The views (templates) are stored in the /views directory (as specified in app.js) and are given the file extension .pug. The method Response.render() is used to render a specified template along with the values of named variables passed in an object, and then send the result as a response. In the code below from /routes/index.js you can see how that route renders a response using the template "index" passing the template variable "title".

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

The corresponding template for the above route is given below (index.pug). We'll talk more about the syntax later. All you need to know for now is that the title variable (with value 'Express') is inserted where specified in the template.

extends layout

block content
  h1= title
  p Welcome to #{title}

Challenge yourself

Create a new route in /routes/users.js that will display the text "You're so cool" at URL /users/cool/. Test it by running the server and visiting http://localhost:3000/users/cool/ in your browser

Summary

You have now created a skeleton website project for the Local Library and verified that it runs using node. Most important, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library.

Next we'll start modifying the skeleton so that works as a library website.

See also

Метки документа и участники

Внесли вклад в эту страницу: MariyaSka, Maxim_Tovchenko, maxno62, ozeep, temenb, daviys
Обновлялась последний раз: MariyaSka,