One place for hosting & domains

      приложения

      Настройка приложения Node.js для работы в среде Ubuntu 20.04


      Введение

      Node.js — среда исполнения JavaScript с открытым исходным кодом, предназначенная для построения серверных и сетевых приложений. Данная платформа работает в операционных системах Linux, macOS, FreeBSD и Windows. Хотя вы можете запускать приложения Node.js через командную строку, этот обучающий модуль посвящен их запуску в качестве службы. Это означает, что они будут перезапускаться при перезагрузке системы или неисправности, и что их можно безопасно использовать в производственной среде.

      В этом обучающем модуле вы научитесь создавать готовую производственную среду Node.js на одном сервере Ubuntu 20.04. Этот сервер будет выполнять приложение Node.js под управлением PM2 и предоставлять пользователям безопасный доступ к приложению через обратный прокси-сервер Nginx. Сервер Nginx обеспечивает поддержку HTTPS с использованием бесплатного сертификата от Let’s Encrypt.

      Предварительные требования

      Этот обучающий модуль предполагает, что у вас имеется следующее:

      Если предварительные требования выполнены, у вас должен быть сервер, обслуживающий используемую по умолчанию страницу назначения вашего домена по адресу https://example.com/.

      Шаг 1 — Установка Node.js

      Для начала мы установим самый быстрый выпуск LTS Node.js, используя архивы пакетов NodeSource.

      Вначале мы установим NodeSource PPA, чтобы получить доступ к его содержимому. Убедитесь, что вы находитесь в домашнем каталоге, и используйте curl для получения скрипта установки для последней версии LTS Node.js из его архивов.

      • cd ~
      • curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh

      Вы можете просмотреть содержимое скрипта с помощью nano или предпочитаемого текстового редактора:

      Завершив проверку скрипта, запустите его от имени пользователя sudo:

      • sudo bash nodesource_setup.sh

      Архив PPA будет добавлен в вашу конфигурацию и кэш локальных пакетов автоматически обновится. После запуска скрипта установки Nodesource вы можете установить пакет Node.js:

      Чтобы проверить номер версии Node.js, установленной на начальном шаге, введите:

      Output

      v14.4.0

      Примечание. При установке из NodeSource PPA исполняемый файл Node.js имеет имя nodejs, а не node.

      Пакет nodejs содержит двоичный файл nodejs, а также диспетчер пакетов npm для модулей Node, так что отдельно устанавливать npm не нужно.

      npm использует файл конфигурации в домашнем каталоге, чтобы отслеживать обновления. Он создается при первом запуске npm. Выполните следующую команду, чтобы проверить установку npm и создать файл конфигурации:

      Output

      6.14.5

      Для работы некоторых пакетов npm (например, требующих компиляцию кода из источника) потребуется установить пакет build-essential:

      • sudo apt install build-essential

      Теперь у вас есть необходимые инструменты для работы с пакетами npm, которые требуют компиляции кода из источника.

      Установив исполняемый модуль Node.js, мы можем перейти к написанию приложения Node.js.

      Шаг 2 — Создание приложения Node.js

      Напишем приложение Hello World, возвращающее «Hello World» в ответ на любые запросы HTTP. Этот образец приложения поможет вам выполнить настройку Node.js. Вы можете заменить его собственным приложением, но при этом обязательно измените приложение для прослушивания подходящих IP-адресов и портов.

      Вначале создадим образец приложения под именем hello.js:

      Вставьте в файл следующий код:

      ~/hello.js

      const http = require('http');
      
      const hostname="localhost";
      const port = 3000;
      
      const server = http.createServer((req, res) => {
        res.statusCode = 200;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Hello World!n');
      });
      
      server.listen(port, hostname, () => {
        console.log(`Server running at http://${hostname}:${port}/`);
      });
      

      Сохраните файл и выйдите из редактора.

      Это приложение Node.js прослушивает заданный адрес (localhost) и порт (3000) и возвращает текст «Hello World!» с кодом успешного выполнения a 200 HTTP. Поскольку мы прослушиваем localhost, удаленные клиенты не смогут подключиться к нашему приложению.

      Чтобы протестировать приложение, введите:

      Результат будет выглядеть следующим образом:

      Output

      Server running at http://localhost:3000/

      Примечание. Такой способ запуска приложения Node.js блокирует дополнительные команды, пока приложение не будет закрыто нажатием CTRL+C.

      Чтобы протестировать приложение, откройте на сервере другой сеанс терминала и подключитесь к localhost с помощью команды curl:

      • curl http://localhost:3000

      Если вы увидите следующий результат, приложение работает нормально и прослушивает правильные адрес и порт:

      Output

      Hello World!

      Если вы не увидите ожидаемого результата, убедитесь, что ваше приложение Node.js запущено и настроено для прослушивание правильных адреса и порта.

      Убедившись, что приложение работает, остановите его (если еще не сделали этого) нажатием CTRL+C.

      Шаг 3 — Установка PM2

      Теперь установим диспетчер процессов PM2, предназначенный для приложений Node.js. PM2 позволяет преобразовывать приложения в демонов, чтобы они работали как службы в фоновом режиме.

      Используйте npm для установки последней версии PM2 на своем сервере:

      • sudo npm install pm2@latest -g

      Опция -g указывает npm выполнить глобальную установку модуля, чтобы он был доступен в масштабе всей системы.

      Вначале используем команду pm2 для запуска вашего приложения hello.js в фоновом режиме:

      Также она добавит ваше приложение в список процессов PM2, которы йвыводится при каждом запуске приложения:

      Output

      ... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

      Как указано выше, PM2 автоматически присваивает App name (основанное на имени файла, без расширения .js) и PM2 id. PM2 также обслуживает другие данные, такие как PID процесса, его текущее состояние и использование памяти.

      Приложения, запускаемые через PM2, автоматически перезапускаются в случае сбоя или прекращения работы приложения, но мы можем выполнить дополнительный шаг, чтобы запускать приложение при запуске системы с помощью субкоманды startup. Эта субкоманда генерирует и настраивает скрипт запуска PM2 и управляемых им процессов при загрузке сервера:

      Последняя строка результатов содержит команду, которую нужно запустить с привилегиями суперпользователя для настройки запуска PM2 при загрузке:

      Output

      [PM2] Init System found: systemd sammy [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

      Запустите команду из результатов, указав свое имя пользователя вместо sammy:

      • sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

      Дополнительно мы можем сохранить список процессов PM2 и соответствующие среды:

      Теперь вы создали блок systemd, который запускает pm2 для вашего пользователя при загрузке. Этот экземпляр pm2 запускает hello.js.

      Запустите службу с помощью команды systemctl:

      • sudo systemctl start pm2-sammy

      Если на этом этапе вы увидите ошибку, вам может потребоваться перезагрузка, которую можно выполнить с помощью sudo reboot.

      Проверьте состояние блока systemd:

      • systemctl status pm2-sammy

      Подробный обзор блока systemd можно найти в разделе Основы работы с Systemd: работа со службами, блоками и журналом.

      В дополнение к уже описанным субкомандам PM2 предоставляет много субкоманд, позволяющих управлять информацией о ваших приложениях и искать такую информацию.

      Остановите приложение с помощью этой команды (укажите имя приложения PM2 или id):

      Перезапустите приложение:

      • pm2 restart app_name_or_id

      Выведем список приложений, управление которыми осуществляет PM2:

      Получим информацию об определенном приложении по имени приложения:

      Монитор процесса PM2 запускается с помощью субкоманды monit. При этом отображается состояние приложение, использование ресурсов ЦП и использование памяти:

      При запуске команды pm2 без аргументов отображается страница справки с примерами использования.

      Теперь ваше приложение Node.js запущено и управляется PM2, и мы можем настроить обратный прокси-сервер.

      Шаг 4 — Настройка Nginx в качестве обратного прокси-сервера

      Ваше приложение запущено и прослушивает localhost, но вам нужно дать пользователям возможность доступа к нему. Для этой цели мы настроим веб-сервер Nginx в качестве обратного прокси-сервера.

      В предварительных обучающих модулях вы настроили конфигурацию Nginx в файле /etc/nginx/sites-available/example.com. Откройте этот файл для редактирования:

      • sudo nano /etc/nginx/sites-available/example.com

      В блоке server должен содержаться блок location /. Замените содержимое этого блока следующей конфигурацией. Если ваше приложение настроено для прослушивания другого порта, измените номер порта в выделенной части на подходящий:

      /etc/nginx/sites-available/example.com

      server {
      ...
          location / {
              proxy_pass http://localhost:3000;
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection 'upgrade';
              proxy_set_header Host $host;
              proxy_cache_bypass $http_upgrade;
          }
      ...
      }
      

      Так сервер настраивается для ответа на запросы root. Если наш сервер доступен по адресу example.com, при попытке доступа к https://example.com/ через браузер будет отправлен запрос hello.js с прослушиванием порта 3000 хоста localhost.

      Вы можете добавить в этот же серверный блок дополнительные блоки location, чтобы предоставить другим приложениям доступ к этому же серверу. Например, если вы используете другое приложение Node.js на порту 3001, вы сможете добавить следующий блок location, чтобы разрешить доступ к нему через https://example.com/app2:

      /etc/nginx/sites-available/example.com — Optional

      server {
      ...
          location /app2 {
              proxy_pass http://localhost:3001;
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection 'upgrade';
              proxy_set_header Host $host;
              proxy_cache_bypass $http_upgrade;
          }
      ...
      }
      

      Завершив добавление блоков location для ваших приложений, сохраните файл и закройте редактор.

      Убедитесь в отсутствии ошибок синтаксиса с помощью следующей команды:

      Перезапустите Nginx:

      • sudo systemctl restart nginx

      Если ваше приложение Node.js запущено и конфигурации вашего приложения и Nginx настроены правильно, вы должны иметь возможность доступа к вашему приложению через обратный прокси-сервер Nginx. Попробуйте открыть URL вашего сервера (публичный IP-адрес или доменное имя).

      Заключение

      Поздравляем! Теперь у вас есть приложение Node.js, работающее за обратным прокси-сервером Nginx на сервере Ubuntu 20.04. Настройка обратного прокси-сервера достаточно гибкая, чтобы предоставить вашим пользователям доступ к другим приложениям или статическому веб-контенту, который вы хотите опубликовать.



      Source link

      Создание и настройка проекта React с помощью приложения Create React App


      Автор выбрал Creative Commons для получения пожертвования в рамках программы Write for DOnations.

      Введение

      React — популярная система JavaScript для создания клиентских приложений. Первоначально эта система была разработана Facebook и быстро стала популярной, поскольку она позволяет разработчикам создавать быстрые приложения на основе интуитивно понятной парадигмы программирования, соединяющей JavaScript с похожим на HTML синтаксисом под названием JSX.

      Раньше для создания нового проекта React требовался сложный процесс, состоящий из множества шагов и включающий систему для сборки, компилятор для конвертации современного синтаксиса в читаемый всеми браузерами код, а также базовую структуру директорий. Однако сейчас появилось приложение Create React App, включающее все пакеты JavaScript, необходимые для запуска проекта React, включая системы компиляции кода, проверки соблюдения стандартов кодирования, тестирования и сборки. Также приложение включает сервер с функцией горячей перезагрузки, обновляющей страницу при внесении изменений в код. Также оно создает структуру директорий и компонентов, позволяя перейти к программированию уже через несколько минут.

      Другими словами, вам не нужно беспокоиться о настройке Webpack или другой системы сборки. Вам не нужно настраивать Babel для компиляции кода для совместимости с разными браузерами. Вам не нужно беспокоиться о работе со сложными системами разработки современных клиентских интерфейсов. Вы можете начать создание кода React с минимумом начальной подготовки.

      К завершению этого обучающего руководства у вас будет работающее приложение React, которое вы сможете использовать как основу для любых будущих приложений. Вы внесете первые изменения в код React, обновите стили и выполните сборку для создания полностью минифицированной версии вашего приложения. Также вы будете использовать сервер с горячей перезагрузкой, чтобы мгновенно получать обратную связь и детально изучать компоненты проекта React. Наконец, вы начнете писать собственные компоненты и создадите структуру, которая сможет расти и адаптироваться вместе с вашим проектом.

      Предварительные требования

      Для прохождения этого обучающего руководства вам потребуется следующее:

      • Node.js версии 10.16.0, установленный на вашем компьютере. Чтобы установить его в macOS или Ubuntu 18.04, следуйте указаниям руководства Установка Node.js и создание локальной среды разработки в macOS или раздела Установка с помощью PPA руководства Установка Node.js в Ubuntu 18.04.

      • Также вам нужно понимать основы языка JavaScript, для изучения которого вам подойдет серия Программирование на JavaScript, а также обладать базовыми знаниями языков HTML и CSS.

      Шаг 1 — Создание нового проекта с помощью приложения Create React App

      На этом шаге мы создадим новое приложение, используя диспетчер пакетов npm для запуска удаленного скрипта. Скрипт скопирует необходимые файлы в новую директорию и установит все зависимости.

      При установке Node вы также установили приложение для управления пакетами npm. npm установит пакеты JavaScript для вашего проекта и будет отслеживать детали проекта. Если вы хотите узнать больше об npm, воспользуйтесь обучающим руководством Использование модулей Node.js с npm и package.json.

      npm также включает инструмент npx, отвечающий за запуск исполняемых пакетов. Это означает, что вы сможете запускать код приложения Create React App без предварительной загрузки проекта.

      Используемый пакет выполнит установку create-react-app в указанную вами директорию. Для начала он создаст в директории новый пакет, которому в этом обучающем руководстве мы присвоим имя digital-ocean-tutorial. Если этой директории не существует, исполняемый пакет просто создаст ее. Скрипт также запустит команду npm install в директории проекта для загрузки всех дополнительных зависимостей.

      Для установки базового проекта выполните следующую команду:

      • npx create-react-app digital-ocean-tutorial

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

      После успешного выполнения скрипта вы увидите соответствующее сообщение:

      Output

      ... Success! Created digital-ocean-tutorial at your_file_path/digital-ocean-tutorial Inside that directory, you can run several commands: npm start Starts the development server. npm run build Bundles the app into static files for production. npm test Starts the test runner. npm run eject Removes this tool and copies build dependencies, configuration files and scripts into the app directory. If you do this, you can’t go back! We suggest that you begin by typing: cd digital-ocean-tutorial npm start Happy hacking!

      your_file_path будет текущим путем. Если вы используете macOS, путь будет выглядеть как /Users/your_username; а если вы используете сервер Ubuntu — /home/your_username.

      Также вы увидите список команд npm для выполнения, сборки, запуска и тестирования вашего приложения. Более подробно вы узнаете об этом в следующем разделе.

      Примечание. Также для JavaScript можно использовать диспетчер пакетов yarn. Он поддерживается Facebook и во многом аналогичен по функционалу npm. Изначально в yarn были добавлены некоторые новые функции, такие как блокировка файлов, однако сейчас они реализованы и в npm. Кроме того, в yarn имеются и другие функции, такие как кэширование в автономном режиме. О других отличиях можно узнать из документации по yarn.

      Если вы ранее устанавливали yarn в вашей системе, вы увидите список команд yarn, таких как yarn start. Эти команды работают так же, как и команды npm. Вы можете запускать команды npm, даже если у вас установлен yarn. Если вы предпочитаете yarn, просто заменяйте npm на yarn во всех будущих командах. Результат будет точно таким же.

      Теперь ваш проект настроен в новой директории. Перейдите в новую директорию:

      • cd digital-ocean-tutorial

      Теперь вы находитесь в корневой директории вашего проекта. Вы уже создали новый проект и добавили в него все зависимости. Однако вы не предприняли никаких действий для запуска проекта. В следующем разделе вы научитесь использовать пользовательские скрипты для сборки и тестирования проекта.

      Шаг 2 — Использование скриптов react-scripts

      На этом шаге вы узнаете о различных скриптах react-scripts, устанавливаемых вместе с репозиторием. Вначале вы запустите скрипт test для выполнения тестового кода. Затем вы запустите скрипт build для создания минифицированной версии. В заключение вы узнаете, как использовать скрипт eject для полного контроля персонализированной настройки.

      Перейдите в директорию проекта и изучите ее. Вы можете открыть всю директорию в текстовом редакторе или вывести файлы из него в терминале с помощью следующей команды:

      Флаг -a обеспечивает добавление в вывод скрытых файлов.

      В любом случае вы увидите примерно следующую структуру:

      Output

      node_modules/ public/ src/ .gitignore README.md package-lock.json package.json

      Расскажем обо всех элементах подробнее:

      • node_modules/ содержит все внешние библиотеки JavaScript, используемые приложением. Вам нечасто потребуется использовать его.

      • Директория public/ содержит базовые файлы HTML, JSON и изображений. Это корневые ресурсы вашего проекта. Вы сможете узнать о них более подробно на шаге 4.

      • В директории src/ содержится код React JavaScript для вашего проекта. В основном вы будете работать именно с этой директорией. Более подробно мы расскажем об этой директории на шаге 5.

      • Файл .gitignore содержит несколько директорий и файлов по умолчанию, которые система контроля исходного кода git будет игнорировать, в том числе директорию node_modules. Игнорируемые элементы — это большие директории или файлы журнала, которые не нужны при контроле исходного кода. Также здесь указаны некоторые директории, которые вы создадите с помощью некоторых скриптов React.

      • README.md — это файл разметки, содержащий много полезной информации о приложении Create React App, в том числе обзор команд и ссылки на расширенные опции конфигурации. Сейчас лучше оставить файл README.md в первозданном виде. По мере развития проекта вы будете заменять данные по умолчанию более подробной информацией о вашем проекте.

      Последние два файла используются вашим диспетчером пакетов. При запуске первоначальной команды npx вы создали базовый проект, а также установили дополнительные зависимости. При установке зависимостей вы создали файл package-lock.json. Этот файл используется npm для проверки точного соответствия версий пакетов. Так вы можете быть уверены, что если кто-то другой установит ваш проект, у него будут идентичные зависимости. Поскольку этот файл создается автоматически, вам нечасто потребуется редактировать его.

      Последний файл — package.json. Он содержит метаданные о вашем проекте, включая заголовок, номер версии и зависимости. Также он содержит скрипты, которые вы можете использовать для запуска проекта.

      Откройте файл package.json в предпочитаемом текстовом редакторе:

      Открыв файл, вы увидите объект JSON, содержащий все метаданные. Если посмотреть на объект scripts, вы увидите, что он содержит четыре разных скрипта: start, build, test и eject.

      Эти скрипты перечислены в порядке важности. Первый скрипт запускает локальную среду разработки, к чему мы перейдем на следующем шаге. Второй скрипт выполняет сборку вашего проекта. Вы узнаете об этом более подробно на шаге 4, но лучше запустить его сейчас и посмотреть, что произойдет.

      Скрипт build

      Для запуска любого скрипта npm нужно просто ввести в терминале команду npm run script_name. Существует несколько особых скриптов, где можно опустить run в составе команды, но вводить команду полностью никогда не будет ошибкой. Чтобы запустить скрипт build, введите в терминале следующую команду:

      Вы немедленно увидите следующее сообщение:

      Output

      > digital-ocean-tutorial@0.1.0 build your_file_path/digital-ocean-tutorial > react-scripts build Creating an optimized production build... ...

      Это покажет вам, что приложение Create React App компилирует ваш код в пригодный для использования пакет.

      После завершения вы увидите следующее:

      Output

      ... Compiled successfully. File sizes after gzip: 39.85 KB build/static/js/9999.chunk.js 780 B build/static/js/runtime-main.99999.js 616 B build/static/js/main.9999.chunk.js 556 B build/static/css/main.9999.chunk.css The project was built assuming it is hosted at the server root. You can control this with the homepage field in your package.json. For example, add this to build it for GitHub Pages: "homepage" : "http://myname.github.io/myapp", The build folder is ready to be deployed. You may serve it with a static server: serve -s build Find out more about deployment here: bit.ly/CRA-deploy

      Выведите содержимое проекта, и вы увидите несколько новых директорий:

      Output

      build/ node_modules/ public/ src/ .gitignore README.md package-lock.json package.json

      Теперь у вас появилась директория build. Если вы открывали файл .gitignore, вы могли заметить, что директория build игнорируется git. Это связано с тем, что директория build просто представляет собой минифицированную и оптимизированную версию других файлов. Контроль версий не требуется, поскольку вы можете в любое время запустить команду build. О результатах выполнения этого скрипта мы поговорим чуть позже, а пока что перейдем к скрипту test.

      Скрипт test

      Скрипт test — один из специальных скриптов, для которых не требуется ключевое слово run, однако он будет работать и с этим ключевым словом. Этот скрипт запускает программу тестирования Jest. Программа тестирования ищет в проекте файлы с расширением .spec.js или .test.js, а затем запускает эти файлы.

      Для запуска скрипта test введите следующую команду:

      После запуска этого скрипта на вашем терминале будут выведены результаты тестирования, а командная строка терминала будет скрыта. Он будет выглядеть примерно так:

      Output

      PASS src/App.test.js ✓ renders learn react link (67ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 4.204s Ran all test suites. Watch Usage › Press f to run only failed tests. › Press o to only run tests related to changed files. › Press q to quit watch mode. › Press p to filter by a filename regex pattern. › Press t to filter by a test name regex pattern. › Press Enter to trigger a test run.

      Здесь нужно обратить внимание на несколько вещей. Во-первых, как говорилось выше, тест автоматически обнаруживает все файлы с тестовыми расширениями, включая .test.js и .spec.js. В нашем случае у нас имеется только один тестовый набор, то есть только один файл с расширением .test.js, и этот набор содержит только один тест. Jest может обнаруживать тесты в иерархии кода, то есть вы можете размещать тесты в директории, и Jest найдет их там.

      Во-вторых, Jest не просто запускает тест один раз и закрывается. Он продолжает работать в терминале. Если вы внесете изменения в исходный код, он проведет тесты снова.

      Также вы можете ограничить состав запускаемых тестов, использовав одну из опций с клавиатуры. Например, если вы наберете o, тесты будут выполняться только с файлами, в которые были внесены изменения. Это поможет вам сэкономить много времени при увеличении объемов тестовых наборов.

      Для выхода из системы тестирования следует ввести q. Сделайте это сейчас, чтобы вернуться в командную строку.

      Скрипт eject

      Последний скрипт называется npm eject. Этот скрипт копирует зависимости и файлы конфигурации в ваш проект, обеспечивая полный контроль над кодом, но при этом извлекая проект из интегрированной системы инструментов приложения Create React App. Сейчас мы не будем запускать этот скрипт, поскольку это действие нельзя отменить, а при его запуске вы потеряете все будущие обновления приложения Create React App.

      Ценность приложения Create React App заключается в том, что вам не нужно беспокоиться о значительном количестве аспектов настройки конфигурации. Для создания современных приложений JavaScript требуется множество разных инструментов, от Webpack и других сборочных систем до Babel и других средств компиляции. Приложение Create React App выполняет за вас все задачи по настройке конфигурации, поэтому извлечение проекта из приложения означает, что вам придется вносить все сложные настройки самостоятельно.

      Минус приложения Create React App заключается в том, что вы не можете полностью персонализировать проект. Для большинства проектов это неважно, однако если вы захотите полностью контролировать все аспекты процесса сборки, вам нужно будет выполнить извлечение кода. Однако, как мы уже говорили выше, после извлечения кода вы не сможете обновлять его с новыми версиями приложения Create React App, и вам придется вручную добавлять все улучшения.

      На данный момент вы выполнили скрипты для сборки и тестирования вашего кода. На следующем шаге мы запустим проект на рабочем сервере.

      Шаг 3 — Запуск сервера

      На этом шаге вы инициализируете локальный сервер и запустите проект в своем браузере.

      Для запуска проекта используется еще один скрипт npm. Как и скрипт npm test, этот скрипт не требует использования команды run. Этот скрипт запускает локальный сервер, выполняет код проекта, запускает программу отслеживания изменений кода и открывает проект в браузере.

      Запустите проект, введя следующую команду в корневой директории проекта. В данном обучающем руководстве в качестве корневой директории проекта выступает директория digital-ocean-tutorial. Откройте ее на отдельном терминале или вкладке, поскольку этот скрипт будет работать все время, пока вы это разрешаете:

      Перед запуском сервера вы ненадолго увидите замещающий текст, а потом появится следующий экран:

      Output

      Compiled successfully! You can now view digital-ocean-tutorial in the browser. http://localhost:3000 Note that the development build is not optimized. To create a production build, use npm run build.

      Если вы запускаете скрипт в локальной системе, он откроет проект в окне браузера и переключит фокус с терминала на браузер.

      Если этого не произойдет, вы можете открыть URL-адрес http://localhost:3000/, чтобы увидеть сайт в работе. Если на порту 3000 уже запущен другой сервер, это не представляет проблемы. Приложение Create React App найдет следующий доступный порт и запустит сервер на нем. Другими словами, если у вас уже запущен проект на порту 3000, новый проект будет запущен на порту 3001.

      При запуске с удаленного сервера вы все равно сможете увидеть свой сайт без дополнительной настройки. Он будет иметь адрес http://your_server_ip:3000. Если у вас включен и настроен брандмауэр, вам нужно будет открыть данный порт на удаленном сервере.

      В браузере вы увидите следующий шаблон проекта React:

      Шаблон проекта React

      Пока скрипт работает, у вас будет активный локальный сервер. Для остановки скрипта следует закрыть окно или вкладку терминала или ввести CTRL+C или ⌘-+c в окне или на вкладке терминала, где выполняется ваш скрипт.

      Вы запустили сервер, и ваш первый код React уже выполняется. Прежде чем вносить любые изменения в код React JavaScript, вам нужно увидеть рендеринг React на странице.

      Шаг 4 — Изменение главной страницы

      На этом шаге мы изменим код в директории public/. В директории public содержится ваша базовая страница HTML. Эта страница будет выступать в качестве корневой для вашего проекта. В будущем вам редко придется изменять эту директорию, однако она представляет собой основу запуска проекта и является ключевой частью проекта React.

      Если вы отключили сервер, запустите его с помощью команды npm start, а затем откройте public/ в предпочитаемом текстовом редакторе в новом окне терминала:

      Также вы можете вывести список файлов с помощью команды ls:

      Вы увидите список файлов следующего вида:

      Output

      favicon.ico logo192.png manifest.json index.html logo512.png robots.txt

      favicon.ico, logo192.png и logo512.png — это значки, которые пользователь будет видеть на вкладке браузера или в телефоне. Браузер автоматически выберет значок подходящего размера. Впоследствии вы можете заменить их на другие значки, которые лучше подойдут для вашего проекта. Пока же вы можете использовать их как есть.

      Файл manifest.json содержит структурированный набор метаданных, описывающий ваш проект. Помимо прочего, в нем указывается, какие значки следует использовать для разных размеров экрана.

      Файл robots.txt содержит информацию для поисковых роботов. Он указывает роботам, какие страницы можно индексировать, а какие нельзя. Вам не нужно изменять ни один из этих файлов, если у вас нет на это важных причин. Например, если вы хотите дать некоторым пользователям URL для доступа к особому контенту, который не должен быть общедоступным, вы можете добавить этот URL в файл robots.txt, и он останется общедоступным, но не будет индексироваться поисковыми системами.

      Файл index.html представляет собой корневую часть вашего приложения. Именно этот файл считывает сервер, и именно его отображает ваш браузер. Откройте файл в текстовом редакторе и посмотрите на него.

      Если вы работаете из командной строки, вы можете использовать следующую команду:

      Вот что вы увидите:

      digital-ocean-tutorial/public/index.html

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          <link rel="icon" href="https://www.digitalocean.com/%PUBLIC_URL%/favicon.ico" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <meta name="theme-color" content="#000000" />
          <meta
            name="description"
            content="Web site created using create-react-app"
          />
          <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
          <!--
            manifest.json provides metadata used when your web app is installed on a
            user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
          -->
          <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
          <!--
            Notice the use of %PUBLIC_URL% in the tags above.
            It will be replaced with the URL of the `public` folder during the build.
            Only files inside the `public` folder can be referenced from the HTML.
      
            Unlike "https://www.digitalocean.com/favicon.ico" or "favicon.ico", "https://www.digitalocean.com/%PUBLIC_URL%/favicon.ico" will
            work correctly both with client-side routing and a non-root public URL.
            Learn how to configure a non-root public URL by running `npm run build`.
          -->
          <title>React App</title>
        </head>
        <body>
          <noscript>You need to enable JavaScript to run this app.</noscript>
          <div id="root"></div>
          <!--
            This HTML file is a template.
            If you open it directly in the browser, you will see an empty page.
      
            You can add webfonts, meta tags, or analytics to this file.
            The build step will place the bundled scripts into the <body> tag.
      
            To begin the development, run `npm start` or `yarn start`.
            To create a production bundle, use `npm run build` or `yarn build`.
          -->
        </body>
      </html>
      

      Сам файл довольно короткий. В части <body> нет изображений или слов. Это связано с тем, что React самостоятельно строит всю структуру HTML и вставляет ее с помощью JavaScript. Однако React нужно знать, куда вставлять код, и для этого и используется файл index.html.

      В текстовом редакторе измените значение тега <title> с React App на Sandbox:

      digital-ocean-tutorial/public/index.html

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          <link rel="icon" href="https://www.digitalocean.com/%PUBLIC_URL%/favicon.ico" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <meta name="theme-color" content="#000000" />
          ...
          <title>Sandbox</title>
        </head>
        <body>
          <noscript>You need to enable JavaScript to run this app.</noscript>
          <div id="root"></div>
          <!--
            This HTML file is a template.
            If you open it directly in the browser, you will see an empty page.
      
            You can add webfonts, meta tags, or analytics to this file.
            The build step will place the bundled scripts into the <body> tag.
      
            To begin the development, run `npm start` or `yarn start`.
            To create a production bundle, use `npm run build` or `yarn build`.
          -->
        </body>
      </html>
      
      

      Сохраните изменения и закройте текстовый редактор. Откройте файл в браузере. Заголовок отображается на вкладке браузера и должен обновиться автоматически. Если этого не произойдет, обновите страницу и посмотрите на изменения.

      Теперь вернитесь в текстовый редактор. Каждый проект React начинается с корневого элемента. На странице может быть несколько корневых элементов, но один должен присутствовать обязательно. Так React узнает, куда поместить сгенерированный код HTML. Найдите элемент <div id="root">. Этот элемент div будет использоваться React для всех будущих обновлений. Измените id с root на base:

      digital-ocean-tutorial/public/index.html

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          ...
        <body>
          <noscript>You need to enable JavaScript to run this app.</noscript>
          <div id="base"></div>
          <!--
            This HTML file is a template.
            If you open it directly in the browser, you will see an empty page.
      
            You can add webfonts, meta tags, or analytics to this file.
            The build step will place the bundled scripts into the <body> tag.
      
            To begin the development, run `npm start` or `yarn start`.
            To create a production bundle, use `npm run build` or `yarn build`.
          -->
        </body>
      </html>
      

      Сохраните изменения.

      В браузере вы увидите сообщение об ошибке:

      Сообщение об ошибке гласит «Target container is not a DOM element» (целевой контейнер не является элементом DOM)

      React искал элемент с id root. Теперь этого элемента нет, и React не может запустить проект.

      Измените имя с base на root:

      digital-ocean-tutorial/public/index.html

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          ...
        <body>
          <noscript>You need to enable JavaScript to run this app.</noscript>
          <div id="root"></div>
          <!--
            This HTML file is a template.
            If you open it directly in the browser, you will see an empty page.
      
            You can add webfonts, meta tags, or analytics to this file.
            The build step will place the bundled scripts into the <body> tag.
      
            To begin the development, run `npm start` or `yarn start`.
            To create a production bundle, use `npm run build` or `yarn build`.
          -->
        </body>
      </html>
      

      Сохраните и закройте файл index.html.

      Вы запустили сервер и внесли небольшое изменение в корневую страницу HTML. Пока еще вы не меняли код JavaScript. В следующем разделе мы начнем изменять код React JavaScript.

      Шаг 5 — Изменение тега заголовка и стилей

      На этом шаге вы внесете первое изменение в компонент React в директории src/. Вы внесете небольшое изменение в код CSS и JavaScript, который будет автоматически обновляться в браузере с помощью встроенной функции горячей перезагрузки.

      Если вы остановили сервер, обязательно перезапустите его с помощью команды npm start. Познакомьтесь с содержимым директории src/. Вы можете открыть полную директорию в предпочитаемом текстовом редакторе или вывести проект на терминал с помощью следующей команды:

      Вы увидите в терминале или текстовом редакторе следующие файлы.

      Output

      App.css App.js App.test.js index.css index.js logo.svg serviceWorker.js setupTests.js

      Рассмотрим каждый из этих файлов по отдельности.

      Вначале вы не будете тратить много времени на файл serviceWorker.js, но он может оказаться важным, когда вы начнете создавать прогрессивные веб-приложения. Сервисный рабочий может выполнять много разных задач, в том числе отправлять push-уведомления и обеспечивать кэширование в автономном режиме, но пока что мы не будем его трогать.

      Далее взглянем на файлы setupTests.js и App.test.js. Они используются для тестовых файлов. При запуске npm test на шаге 2 скрипт уже запускал эти файлы. Файл setupTests.js небольшой и содержит несколько настраиваемых методов expect. Вы узнаете о них больше в следующих обучающих руководствах этой серии.

      Откройте файл App.test.js:

      Когда вы откроете этот файл, вы увидите простой тест:

      digital-ocean-tutorial/src/App.test.js

      import React from 'react';
      import { render } from '@testing-library/react';
      import App from './App';
      
      test('renders learn react link', () => {
        const { getByText } = render(<App />);
        const linkElement = getByText(/learn react/i);
        expect(linkElement).toBeInTheDocument();
      });
      

      Этот тест проверяет наличие в документе фразы learn react. Если вы вернетесь в браузер, где запущен ваш проект, вы увидите фразу на странице. Тестирование React отличается от большинства блочных тестов. Поскольку компоненты могут содержать и визуальную информацию (например разметку), и логику управления данными, традиционные блочные тесты могут не сработать. Тестирование React скорее является формой функционального тестирования или тестирования интеграции.

      Далее вы видите несколько файлов стилей: App.css, index.css и logo.svg. Существует много вариантов работы со стилями в React, но проще всего написать простой код CSS, не требующий дополнительной настройки.

      Здесь имеется несколько файлов CSS, поскольку вы можете импортировать стили в компонент, как если бы они представляли собой другой файл JavaScript. Поскольку у вас имеется возможность импортировать CSS в компонент напрямую, вы также можете разделить файл CSS для его применения к отдельному компоненту. Так вы разделяете области беспокойства. Вы не храните все файлы CSS отдельно от JavaScript. Вместо этого все элементы CSS, JavaScript, разметки и изображений сгруппированы вместе.

      Откройте файл App.css в предпочитаемом текстовом редакторе. Если вы работаете из командной строки, вы можете использовать следующую команду:

      Вы увидите следующий код:

      digital-ocean-tutorial/src/App.css

      .App {
        text-align: center;
      }
      
      .App-logo {
        height: 40vmin;
        pointer-events: none;
      }
      
      @media (prefers-reduced-motion: no-preference) {
        .App-logo {
          animation: App-logo-spin infinite 20s linear;
        }
      }
      
      .App-header {
        background-color: #282c34;
        min-height: 100vh;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        font-size: calc(10px + 2vmin);
        color: white;
      }
      
      .App-link {
        color: #61dafb;
      }
      
      @keyframes App-logo-spin {
        from {
          transform: rotate(0deg);
        }
        to {
          transform: rotate(360deg);
        }
      }
      

      Это стандартный файл CSS без специальных инструментов предварительной обработки CSS. Если хотите, вы можете добавить их позднее, но вначале у вас будут только простые файлы CSS. Создатели приложения Create React App старались не делать его безапелляционным, но при этом предоставить полностью готовую среду.

      Вернемся к файлу App.css. Одно из преимуществ приложения Create React заключается в том, что оно наблюдает за всеми файлами, и при внесении изменения вы увидите его в браузере без перезагрузки.

      Чтобы увидеть это, внесем небольшое изменение в параметр background-color в файле App.css. Измените его с #282c34 на blue, а затем сохраните файл. Окончательный стиль будет выглядеть следующим образом:

      digital-ocean-tutorial/src/App.css

      .App {
        text-align: center;
      }
      ...
      .App-header {
        background-color: blue
        min-height: 100vh;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        font-size: calc(10px + 2vmin);
        color: white;
      }
      ...
      
      @keyframes App-logo-spin {
        from {
          transform: rotate(0deg);
        }
        to {
          transform: rotate(360deg);
        }
      }
      

      Проверьте браузер. Вот как это выглядело раньше:

      Приложение React с темным фоном

      Вот как это будет выглядеть после изменения:

      Приложение React с синим фоном

      Измените значение background-color обратно на #282c34.

      digital-ocean-tutorial/src/App.css

      .App {
        text-align: center;
      
      ...
      
      .App-header {
        background-color: #282c34
        min-height: 100vh;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        font-size: calc(10px + 2vmin);
        color: white;
      }
      
      ...
      
      @keyframes App-logo-spin {
        from {
          transform: rotate(0deg);
        }
        to {
          transform: rotate(360deg);
        }
      }
      

      Сохраните и закройте файл.

      Вы внесли небольшое изменение в файл CSS. Теперь внесем изменения в код React JavaScript. Для начала откройте файл index.js.

      Вы увидите следующее:

      digital-ocean-tutorial/src/index.js

      import React from 'react';
      import ReactDOM from 'react-dom';
      import './index.css';
      import App from './App';
      import * as serviceWorker from './serviceWorker';
      
      ReactDOM.render(<App />, document.getElementById('root'));
      
      // If you want your app to work offline and load faster, you can change
      // unregister() to register() below. Note this comes with some pitfalls.
      // Learn more about service workers: https://bit.ly/CRA-PWA
      serviceWorker.unregister();
      

      Прежде всего, вы импортируете React, ReactDOM, index.css, App и serviceWorker. Импортируя React, вы фактически извлекаете код для конвертации JSX в JavaScript. JSX — это элементы в стиле HTML. Обратите внимание, что при использовании App вы обращаетесь с ним как с элементом HTML <App />. Вы узнаете об этом подробнее из следующих обучающих руководств этой серии.

      ReactDOM — это код, который связывает ваш код React с базовыми элементами, такими как страница index.html, которую мы увидели в public/. Посмотрите на следующую выделенную строку:

      digital-ocean-tutorial/src/index.js

      ...
      import * as serviceWorker from './serviceWorker';
      
      ReactDOM.render(<App />, document.getElementById('root'));
      ...
      serviceWorker.unregister();
      

      Этот код предписывает React найти элемент с id root и вставить в него код React. <App/> — это корневой элемент, от которого идут все ответвления. Это исходная точка для всего будущего кода React.

      Вверху файла имеется несколько операций импорта. Мы импортируем index.css, но ничего не делаем с этим файлом. Импортируя его, мы предписываем Webpack через скрипты React включить этот код CSS в окончательную скомпилированную версию пакета. Если его не импортировать, он не будет отображаться.

      Выйдите из файла src/index.js.

      Пока что вы еще не видели ничего, что вы видите в браузере. Чтобы увидеть это, откройте файл App.js:

      Код в этом файле выглядит как набор стандартных элементов HTML. Вы увидите следующее:

      digital-ocean-tutorial/src/App.js

      import React from 'react';
      import logo from './logo.svg';
      import './App.css';
      
      function App() {
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <p>
                Edit <code>src/App.js</code> and save to reload.
              </p>
              <a
                className="App-link"
                href="https://reactjs.org"
                target="_blank"
                rel="noopener noreferrer"
              >
                Learn React
              </a>
            </header>
          </div>
        );
      }
      
      export default App;
      

      Измените содержимое тега <p> с Edit <code>src/App.js</code> and save to reload. на Hello, world и сохраните изменения.

      digital-ocean-tutorial/src/App.js

      ...
      
      function App() {
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <p>
                  Hello, world
              </p>
              <a
                className="App-link"
                href="https://reactjs.org"
                target="_blank"
                rel="noopener noreferrer"
              >
                Learn React
              </a>
            </header>
          </div>
        );
      }
      ...
      

      Переключитесь в браузер, и вы увидите изменения:

      Приложение React с текстом "Hello, world" в теге абзаца

      Вы внесли первое изменение в компонент React.

      Прежде чем заканчивать, обратите внимание еще на несколько вещей. В этом компоненте мы импортируем файл logo.svg и назначаем его переменной. Затем в элементе <img> мы добавляем этот код как src.

      Здесь происходит еще несколько вещей. Посмотрите на элемент img:

      digital-ocean-tutorial/src/App.js

      ...
      function App() {
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <p>
                  Hello, world
              </p>
      ...
      

      Обратите внимание, как вы передаете logo в фигурных скобках. Каждый раз, когда вы передаете атрибуты, которые не являются строками или числами, вам нужно будет использовать фигурные скобки. React обрабатывает их как элементы JavaScript, а не как строки. В этом случае вы не импортируете образ, а ссылаетесь на него. Когда Webpack выполняет сборку проекта, он обрабатывает образ и задает для источника соответствующее место.

      Закройте текстовый редактор.

      Если вы посмотрите на элементы DOM в браузере, вы увидите, что он добавляет путь. Если вы используете Chrome, вы можете просмотреть элемент, щелкнув его правой кнопкой мыши и выбрав пункт Inspect.

      Вот как это будет выглядеть в браузере:

      Инспектирование элемента с помощью инструментов chrome для разработчиков

      В DOM содержится следующая строка:

      <img src="https://www.digitalocean.com/static/media/logo.5d5d9eef.svg" class="App-logo" alt="logo">
      

      Ваш код будет немного отличаться, поскольку у логотипа другое имя. Webpack нужно убедиться, что путь изображения уникальный. Так что даже если вы импортируете изображения с одинаковым именем, они будут сохраняться на разных путях.

      Вы внесли небольшое изменение в код React JavaScript. На следующем шаге мы используем команду build для минификации кода в небольшой файл, который можно будет развернуть на сервере.

      Шаг 6 — Сборка проекта

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

      Вернитесь в терминал и выполните сборку проекта. Вы уже запускали эту команду, но напомним, что она запускает скрипт build. В результате будет создан новая директория с комбинированными и минифицированными файлами. Для выполнения сборки запустите следующую команду из корневой директории проекта:

      Возможна небольшая задержка, пока код будет компилироваться, а после завершения компиляции будет создана новая директория build/.

      Откройте build/index.html в текстовом редакторе.

      Вы увидите примерно следующее:

      digital-ocean-tutorial/build/index.html

      <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="https://www.digitalocean.com/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="http://www.digitalocean.com/logo192.png"/><link rel="manifest" href="http://www.digitalocean.com/manifest.json"/><title>React App</title><link href="http://www.digitalocean.com/static/css/main.d1b05096.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,a,p=r[0],l=r[1],c=r[2],i=0,s=[];i<p.length;i++)a=p[i],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in l)Object.prototype.hasOwnProperty.call(l,n)&&(e[n]=l[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,c||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,p=1;p<t.length;p++){var l=t[p];0!==o[l]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/";var p=this["webpackJsonpdo-create-react-app"]=this["webpackJsonpdo-create-react-app"]||[],l=p.push.bind(p);p.push=r,p=p.slice();for(var c=0;c<p.length;c++)r(p[c]);var f=l;t()}([])</script><script src="/static/js/2.c0be6967.chunk.js"></script><script src="/static/js/main.bac2dbd2.chunk.js"></script></body></html>
      

      В директории сборки весь код компилируется и минифицируется до наименьшего полезного состояния. Читаемость кода неважна, поскольку этот код не предназначен для чтения человеком. При такой минификации код занимает намного меньше места, но при этом работает. В отличие от таких языков как Python, пробел не меняет интерпретацию кода компьютером.

      Заключение

      В этом обучающем руководстве вы создали свое первое приложение React и настроили проект с помощью инструментов сборки JavaScript без необходимости вдаваться в технические детали. В этом и заключается польза приложения Create React App: вам не нужно знать все, чтобы начать работу. Приложение позволяет игнорировать сложные этапы сборки и сосредоточиться исключительно на коде React.

      Вы изучили команды для запуска, тестирования и сборки проекта. Вы будете использовать эти команды регулярно, так что запомните их для будущих обучающих руководств. Не менее важно, что вы изменили свой первый компонент React.

      Если вы хотите увидеть React в действии, пройдите обучающее руководство Отображение данных из DigitalOcean API с помощью React.



      Source link

      Создание приложения с вдохновляющими цитатами с помощью AdonisJs и MySQL


      Автор выбрал Tech Education Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

      AdonisJs — это веб-инфраструктура Node.js, написанная на простом языке JavaScript, поддерживаемом всеми основными операционными системами. Она использует популярную схему MVC (модель — представление — контроллер) и предлагает стабильную экосистему для написания серверной части веб-приложений. Инфраструктура поддерживает удобную аутентификацию, SQL ORM (реляционные карты объектов), миграцию и пополнение баз данных. Архитектура AdonisJs похожа на архитектуру веб-инфраструктуры Laravel для приложений PHP и имеет такую же структуру папок и несколько сходных концепций настройки.

      По умолчанию AdonisJs использует систему шаблонов Edge, разработанную для интуитивно простого использования. Как и в Laravel, в AdonisJs имеется система ORM под названием Lucid, служащая интерфейсом для взаимодействия между моделями приложения и базой данных. С помощью AdonisJs разработчики могут создавать комплексные приложения, где серверная часть отвечает за применение бизнес-логики, маршрутизацию и рендеринг всех страниц приложения. Также можно создать API веб-служб для возврата ответов JSON от контроллера. Эти веб-службы можно использовать с помощью клиентских инфраструктур, таких как Vue.js, React и Angular.

      В этом обучающем руководстве мы создадим приложение с помощью AdonisJs, используя CLI. Мы создадим маршруты, контроллеры, модели и представления приложения, а также проведем проверки форм. В качестве примера для этого обучающего руководства мы выбрали приложение, в которое пользователь может входить для создания вдохновляющих цитат. Это демонстрационное приложение позволит выполнять операции создания, чтения, обновления и удаления (CRUD).

      Предварительные требования

      Для прохождения этого обучающего руководства вам потребуется следующее:

      • Локальная установка Node.js (версия не ниже 8) и npm (версия не ниже 3.0). Node.js — это среда исполнения на базе JavaScript, позволяющая выполнять код за пределами браузера. Она содержит предустановленный диспетчер пакетов npm, позволяющий устанавливать и обновлять пакеты. Чтобы установить его в macOS или Ubuntu 18.04, следуйте указаниям руководства Установка Node.js и создание локальной среды разработки в macOS или раздела Установка с помощью PPA руководства Установка Node.js в Ubuntu 18.04.
      • Установленная на компьютере СУБД MySQL. Следуйте приведенным здесь инструкциям для ее загрузки и установки в выбранной операционной системе. Для успешной установки MySQL можно использовать Homebrew для Mac или следовать указаниям руководства Установка MySQL в Ubuntu 18.04 для установки этой СУБД в Ubuntu 18.04.
      • Понимание основных принципов JavaScript; ознакомьтесь с нашей серией Программирование на JavaScript.
      • Установленный текстовый редактор, например Visual Studio Code, Atom или Sublime Text.

      Примечание. Для разработки в этом обучающем руководстве будет использоваться компьютер под управлением macOS. Если вы используете другую операционную систему, вам может потребоваться использовать права sudo для выполнения команд npm на первых шагах.

      Шаг 1 — Установка Adonis CLI

      В этом разделе мы установим Adonis CLI и все его требуемые пакеты на наш локальный компьютер. CLI позволяет создать структуру нового проекта AdonisJs, а также создать и сгенерировать шаблоны контроллеров, связующих элементов и моделей в вашем приложении. Также вы создадите базу данных для проекта.

      Выполните следующую команду для глобальной установки AdonisJs CLI на компьютере с помощью npm:

      После завершения процесса установки введите в терминал следующую команду для подтверждения установки AdonisJs и просмотра текущей версии:

      Вы увидите вывод с указанием текущей версии AdonisJs:

      Output

      4.1.0

      Мы успешно установили AdonisJs CLI и теперь можем использовать команду adonis для установки новых проектов AdonisJs, управления проектами и генерирования требуемых файлов, в том числе контроллеров, моделей и т. д.

      Теперь мы можем перейти к созданию нового проекта AdonisJs, используя команду adonis, как показано здесь:

      • adonis new adonis-quotes-app

      Приведенная выше команда создаст приложение adonis-quotes-app в новой директории с тем же именем внутри директории локального проекта, используя соответствующую структуру AdonisJs MVC.

      Перейдите в папку нового приложения:

      Запустите приложенеи с помощью следующей команды:

      Эта команда запустит сервер разработки на порту по умолчанию 3333, как указано внутри файла root .env для вашего приложения. Введите адрес http://localhost:3333 для просмотра приветственной страницы AdonisJs.

      Приветственная страница AdonisJs

      Теперь мы завершим настройку базы данных. Здесь вы установите драйвер mysql для подключения к вашему серверу MySQL из вашего приложения Node.js с помощью npm. Для начала вернитесь в терминал, где запущено приложение, остановите процесс нажатием CTRL + C и запустите следующую команду:

      Вы успешно установили драйвер MySQL Node.js для этого приложения, и теперь вам нужно создать базу данных приложения и настроить подключение к ней.

      Последняя версия MySQL, установленная согласно указаниям предварительных требований обучающего руководства, использует плагин аутентификации по умолчанию под названием caching_sha2_password. Этот плагин в настоящее время не поддерживается драйверами Node.js для MySQL. Чтобы избежать проблем при подключении вашего приложения к базе данных, вам нужно будет создать нового пользователя MySQL и использовать поддерживаемый плагин аутентификации mysql_native_password.

      Для начала откройте клиент MySQL, используя учетную запись root:

      В диалоге введите пароль учетной записи root, заданный во время установки MySQL.

      Затем создайте пользователя и пароль, используя плагин mysql_native_password:

      • CREATE USER 'sammy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

      Результат будет выглядеть следующим образом:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Создайте базу данных приложения с помощью следующей команды:

      Результат будет выглядеть следующим образом:

      Output

      Query OK, 1 row affected (0.03 sec)

      Вы успешно создали базу данных для своего приложения.

      Теперь активируйте доступ к созданной базе данных для нового пользователя MySQL. Запустите следующую команду для предоставления всех привилегий пользователю в базе данных:

      • GRANT ALL PRIVILEGES ON adonis.* TO 'sammy'@'localhost';

      Перезагрузите таблицы grant, запустив следующую команду для применения внесенных изменений:

      Результат будет выглядеть следующим образом:

      Output

      Query OK, 0 rows affected (0.00 sec)

      Закройте клиент MySQL с помощью следующей команды:

      Мы успешно установили AdonisJs CLI, создали новый проект AdonisJs и выполнили установку mysql с помощью npm. Также мы создали базу данных для этого приложения и настроили пользователя MySQL с соответствующими правами доступа к нему. Базовая конфигурация приложения готова, и на следующем шаге мы начнем создавать необходимые представления для вашего приложения.

      Шаг 2 — Использование системы шаблонов Edge

      AdonisJs поставляется с собственной системой шаблонов Edge. Это позволяет создать многоразовый шаблон HTML и внести в приложение логику клиентской части с минимальным объемом кода. Edge дает разработчикам приложений JavaScript инструменты для создания схемы на базе компонентов, написания условных выражений, использования итераций и создания уровней представлений для хранения логики. Все файлы шаблонов с расширением .edge хранятся в директории resources/views.

      Далее указаны представления, необходимые приложению для надлежащей работы:

      • Генеральный макет. С помощью Edge вы можете создать страницу, содержащую таблицы CSS, общие файлы JavaScript, jQuery и части пользовательского интерфейса, которые будут едиными для всего приложения, в том числе панель навигации, логотип, заголовок и т. д. После создания генерального макета он будет наследоваться другими представлениями (страницами) вашего приложения.
      • Представление указателя. Эта страница будет использовать генеральный макет для наследования общих файлов, а также выполнять рендеринг содержимого для главной страницы приложения.
      • Страница входа. Эта страница также будет использовать генеральный макет, а также будет выполнять рендеринг формы с полями ввода имени пользователя и пароля для входа пользователей в систему.
      • Страница регистрации. Здесь пользователи найдут форму для регистрации и сохранения своих реквизитов в базе данных.
      • Страница создания цитаты. Пользователи будут использовать эту страницу для создания вдохновляющих цитат.
      • Страница редактирования цитаты. Пользователи будут использовать эту страницу для редактирования цитат.
      • Страница просмотра цитаты. Пользователи будут использовать эту страницу для просмотра определенных цитат.

      Для начала используйте команду adonis для создания страницы генерального макета, как показано здесь:

      • adonis make:view layouts/master

      Результат будет выглядеть примерно так:

      Output

      ✔ create resources/views/layouts/master.edge

      Эта команда автоматически создаст файл master.edge в папке resources/views/layouts. Откройте новый файл:

      • nano resources/views/layouts/master.edge

      Добавьте в него следующий код:

      /resources/views/layouts/master.edge

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <title>adonis-quotes-app</title>
          {{ style('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') }}
          {{ style('style') }}
          {{ script('https://code.jquery.com/jquery-3.3.1.slim.min.js') }}
      </head>
      <body>
          <div class="container-fliud">
              @include('navbar')
              @!section('content')
          </div>
          {{ script('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js') }}
      
      </body>
      </html>
      

      В этот файл добавляются файлы CDN для Bootstrap CSS, Bootstrap JavaScript и jQuery. Также добавляется имя глобального файла CSS style.css, а в div добавляется частичный файл с именем navbar. Для повторного использования требуемых фрагментов кода HTML (например, nav или footer) на разных страницах приложения можно использовать частичные файлы. Это небольшие файлы, содержащие повторяющийся код и позволяющие быстро обновлять код этих элементов в одном месте, а не на каждой странице по отдельности. Файл navbar содержит разметку для кнопок Вход и Регистрация, логотип и ссылку на главную страницу.

      С этим файлом все последующие страницы этого приложения смогут использовать генеральный макет и выводить панель навигации без написания соответствующего кода для каждой страницы. Мы создадим этот файл navbar на следующих шагах этого обучающего руководства.

      В заключение мы определим тэг раздела @! section(), чтобы включить контент других страниц и обеспечить их рендеринг в генеральном макете. Чтобы эта система работала ожидаемым образом, все новые страницы на основе генерального макета должны также определять тег раздела с одним и тем же именем (т. е. @section('content')).

      Сохраните и закройте файл, когда закончите его редактирование.

      Далее мы используем команду adonis для создания панели навигации:

      Результат будет выглядеть примерно так:

      Output

      ✔ create resources/views/navbar.edge

      Откройте созданный файл:

      • nano resources/views/navbar.edge

      Затем добавьте в него следующий код:

      /resources/views/navbar.edge

      <nav class="navbar navbar-expand-lg navbar-dark text-white">
          <a class="navbar-brand" >LOGO</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
          </button>
      
          <div class="collapse navbar-collapse" id="navbarNav">
              <ul class="navbar-nav">
                  <li class="nav-item active ">
                      <a class="btn text-white" href="https://www.digitalocean.com/">Home</a>
                  </li>
              </ul>
          </div>
          <div class="navbar-right" id="navbarNav">
              @loggedIn
                  <ul class="navbar-nav">
                          <li>
                              <div class="text-right">
                                   <a href="{{route('create.quote')}}" class="btn btn-outline-primary">Create Quote</a>
                              </div>
                          </li>
      
                      <li class="nav-item dropdown">
                          <a class="nav-link dropdown-toggle" href="https://www.digitalocean.com/#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                             {{ auth.user.username}}
                          </a>
                          <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                              <form method="POST" action="{{route('logout')}}">
                                  {{ csrfField() }}
                                    <button  type="submit" class="dropdown-item" href="">logout</button>
                              </form>
                          </div>
                      </li>
                  </ul>
              @else
                  <ul class="navbar-nav">
                      <li class="nav-item active pr-2">
                          <a href="{{route('login.create')}}" class="btn btn-outline-danger">
                            login
                          </a>
                      </li>
                      <li class="nav-item active pr-2">
                          <a href="{{route('register.create')}}" class="btn btn-outline-primary">
                              Register
                          </a>
                      </li>
                  </ul>
              @endloggedIn
          </div>
      </nav>
      

      В дополнение к определениям ссылок на главную страницу и кнопок для регистрации и входа мы добавим тег @loggedIn. С этим тегом мы можем написать условное выражение для прошедшего аутентификацию пользователя и выводить соответствующее содержание, когда это требуется. Для прошедшего аутентификацию пользователя приложение отображает имя пользователя и кнопку создания новой цитаты. Если пользователь не прошел аутентификацию, приложение будет отображать кнопку для входа или регистрации. Эта страница будет добавляться как часть каждой другой страницы, как и в случае с генеральным макетом приложения.

      Сохраните и закройте файл.

      Теперь мы создадим страницу указателя, которую используем в качестве главной страницы приложения. Она выполняет рендеринг и выводит список всех вдохновляющих цитат, написанных пользователями:

      Вы увидите примерно следующий результат:

      Output

      ✔ create resources/views/index.edge

      Созданный нами файл будет располагаться в директории resources/views/index.edge. Откройте файл:

      • nano resources/views/index.edge

      Добавьте следующий код:

      /resources/views/index.edge

      @layout('layouts/master')
      @section('content')
      
      <div class="container">
          <div class="text-center">
              @if(flashMessage('successmessage'))
                  <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
              @endif
          </div>
          <div class="row">
              @each(quote in quotes)
                  <div class="col-md-4 mb-4 quote-wrapper">
                      <a href="https://www.digitalocean.com/view-quote/{{quote.id}}" class="w-100">
                          <div class="card shadow-lg bg-dark text-white">
                              <div class="card-body">
                                  <blockquote class="blockquote mb-0">
                                      <p>{{quote.body}}</p>
                                      <footer class="blockquote-footer">
                                          <cite title="Source Title"> {{quote.username}}</cite>
                                      </footer>
                                  </blockquote>
                                  @if(auth.user.id == quote.user_id)
                                    <div>
                                      <a  href="http://www.digitalocean.com/edit-quote/{{quote.id}}" class="btn btn-primary">edit</a>
                                      <a href="http://www.digitalocean.com/delete-quote/{{quote.id}}" class="btn btn-danger">delete</a>
                                    </div>
                                  @endif
                              </div>
                          </div>
                      </a>
                  </div>
              @else
               <div class="col-md-12 empty-quote text-center">
                      <p>No inspirational quote has been created</p>
               </div>
              @endeach
          </div>
      </div>
      @endsection
      

      Здесь вы указываете, что это представление будет использовать макет master посредством его расширения. Теперь эта страница имеет доступ ко всем библиотекам, таблицам стилей и файлу navbar в составе макета master. Далее мы выполним итерацию по массиву цитат, используя встроенный тег @each. Массив quotes будет передаваться в это представление из модуля QuoteController, который мы создадим на следующих шагах этого обучающего руководства. В случае отсутствия цитат будет выведено соответствующее сообщение.

      Сохраните и закройте файл.

      Для создания страницы входа запустите в терминале следующую команду:

      • adonis make:view auth/login

      Вы увидите примерно следующий результат:

      Output

      ✔ create resources/views/auth/login.edge

      Система автоматически создаст папку auth в директории resources/views, а также создаст в ней файл login.edge. Откройте файл login.edge:

      • nano resources/views/auth/login.edge

      Добавьте следующее содержимое:

      /resources/views/auth/login.edge

      @layout('layouts/master')
      @section('content')
        <div class="container">
          <div class="row">
            <div class="col-md-4 shadow bg-white mt-5 rounded offset-md-4">
              <form method="POST" action="{{route('login.store')}}">
                {{ csrfField() }}
                  <div>
                    @if(flashMessage('successmessage'))
                      <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
                    @endif
                  </div>
                  <div class="form-group">
                    <label for="email">Email address</label>
                    <input type="email" class="form-control" id="email" name="email" value="{{old('email','')}}"  placeholder="Enter email">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                  </div>
                  <div class="form-group">
                    <label for="pasword">Password</label>
                    <input type="password" class="form-control" id="password" name="password" value="{{old('password','')}}" placeholder="Password">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                  </div>
      
                  <div class="text-center">
                    <button type="submit" class="btn btn-primary">Submit</button>
                  </div>
              </form>
            </div>
          </div>
        </div>
      @endsection
      

      В этом файле хранится форма, содержащая элементы ввода, которые вы будете использовать для получения имени пользователя и пароля зарегистрированного пользователя, прежде чем он сможет пройти аутентификацию и начать создавать цитаты. Еще один важный элемент на этой странице — {{ csrfField() }}. Это глобальная переменная, которую AdonisJs будет использовать для передачи токена доступа CSRF при отправке запросов POST, PUT и DELETE из приложения.

      Она размещена для защиты вашего приложения от атак методом подделки межсайтовых запросов (CSRF). Она работает посредством генерирования для каждого посещающего сайт пользователя уникального секрета CSRF. При отправке пользователями запроса HTTP через клиент для этого секрета генерируется соответствующий токен, передаваемый вместе с запросом. Это позволяет связующему элементу, создаваемому для этого запроса в AdonisJs, проверять корректность токена и секрета CSRF и их принадлежность пользователю, прошедшему аутентификацию.

      Сохраните и закройте файл после завершения.

      Далее мы создадим страницу регистрации, используя следующую команду:

      • adonis make:view auth/register

      Вы увидите примерно следующий вывод:

      Output

      ✔ create resources/views/auth/register.edge

      Найдите и откройте созданный файл в директории resources/views/auth/register.edge:

      • nano resources/views/auth/register.edge

      Добавьте следующий код:

      resources/views/auth/register.edge

      @layout('layouts/master')
      @section('content')
        <div class="container ">
          <div class="row">
              <div class="col-md-4  bg-white p-3 mt-5 shadow no-border rounded offset-md-4">
                <form method="POST" action="{{route('register.store')}}">
                  {{ csrfField() }}
                    <div class="form-group">
                      <label for="name">Fullname</label>
                      <input type="text" class="form-control" id="name" name="name"  value="{{old('name','')}}" placeholder="Enter Fullname">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('name'), hasErrorFor('name')) }}
                    </div>
                    <div class="form-group">
                      <label for="email">Email address</label>
                      <input type="email" class="form-control" id="email"  name="email" value="{{old('email','')}}" placeholder="Enter email">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                    </div>
                    <div class="form-group">
                      <label for="pasword">Password</label>
                      <input type="password" class="form-control" id="password" name="password" placeholder="Password">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                    </div>
                    <div class="text-center">
                        <button type="submit" class="btn btn-primary">Submit</button>
                    </div>
                </form>
              </div>
          </div>
        </div>
      @endsection
      

      Как и в случае со страницей входа, этот файл содержит форму HTML с полями ввода имени, электронной почты и пароля пользователя при регистрации. Также здесь присутствует переменная {{ csrfField() }}, поскольку она требуется для каждого запроса post для приложения AdonisJs.

      Сохраните и закройте файл.

      Теперь мы сгенерируем новый файл для создания вдохновляющей цитаты, запустив следующую команду из терминала:

      • adonis make:view quotes/create-quote

      Вы увидите примерно следующее:

      Output

      ✔ create resources/views/quotes/create-quote.edge

      Откройте resources/views/quotes/create-quote.edge:

      • nano resources/views/quotes/create-quote.edge

      Добавьте следующее содержание:

      /resources/views/quotes/create-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-3"></div>
              <div class="col-md-6 shadow bg-white mt-5 rounded p-3">
                  <div class="float-right">
                      <a href="https://www.digitalocean.com/" class="btn btn-outline-dark ">back</a>
                  </div>
                      <br>
      
                  <div class="clear-fix"></div>
                      <form method="POST" action="{{route('store.quote')}}">
                          {{ csrfField() }}
                          <div class="form-group">
                              <label for="quote">Create Quote</label>
                              <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="Write an inspirational quote"></textarea>
                          </div>
      
                          <div class="text-center">
                              <button type="submit" class="btn btn-primary">Submit</button>
                          </div>
                      </form>
                  </div>
              </div>
              <div class="col-md-3"></div>
          </div>
      </div>
      @endsection
      

      Эта страница расширяет генеральный макет и содержит форму HTML с элементом текстовой области, позволяющим пользователю вводить текст в нескольких строках, после чего этот текст отправляется и обрабатывается по заданному маршруту.

      Сохраните и закройте файл после завершения.

      Далее мы создадим страницу для редактирования конкретной цитаты. Запустите в терминале следующую команду:

      • adonis make:view quotes/edit-quote

      Результат будет выглядеть следующим образом:

      Output

      ✔ create resources/views/quotes/edit-quote.edge

      Откройте файл с помощью следующей команды:

      • nano resources/views/quotes/edit-quote.edge

      Добавьте следующее содержание в файл resources/views/quotes/edit-quote:

      /resources/views/quotes/edit-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 shadow bg-white rounded p-3 offset-md-3">
                  <div class="float-right">
                      <a href="https://www.digitalocean.com/" class="btn btn-outline-dark ">back</a>
                  </div>
                  <br>
      
                  <div class="clear-fix"></div>
                  <form method="POST" action="/update-quote/{{quote.id}}">
                      {{ csrfField() }}
                      <div class="form-group">
                          <label for="pasword">Edit Quote</label>
                          <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="write the inspirational quote">{{quote.body}}</textarea>
                      </div>
                      <div class="text-center">
                          <button type="submit" class="btn btn-primary">Update</button>
                      </div>
      
                  </form>
              </div>
          </div>
      </div>
      @endsection
      

      Содержание этой страницы похоже на содержание файла create-quote.edge. Отличие заключается в том, что она содержит данные конкретной цитаты, которую нужно отредактировать: <form method="POST" action="/update-quote/{{quote.id}}">.

      Сохраните и закройте файл.

      В заключение мы сгенерируем страницу для просмотра одной вдохновляющей цитаты:

      • adonis make:view quotes/quote

      Вы увидите примерно следующий вывод:

      Output

      ✔ create resources/views/quotes/quote.edge

      Откройте файл с помощью следующей команды:

      • nano resources/views/quotes/quote.edge

      Добавьте следующий код:

      /resources/views/quotes/quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 offset-md-3">
                  <div class="card shadow-lg bg-dark text-white">
                      <div class="card-body">
                          <div class="float-right">
                              <a href="https://www.digitalocean.com/" class="btn btn-outline-primary ">back</a>
                          </div>
                              <br>
                          <div class="clear-fix"></div>
                          <blockquote class="blockquote mb-0">
                              <p>{{quote.body}}</p>
                              <footer class="blockquote-footer">
                                  <cite title="Source Title">{{quote.username}}</cite>
                              </footer>
                          </blockquote>
                      </div>
                  </div>
              </div>
          </div>
      </div>
      @endsection
      

      Эта страница выполняет рендеринг деталей конкретной цитаты, включая тело цитаты quote.body и пользователя, создавшего цитату, quote.username.

      После завершения работы с этим файлом сохраните и закройте его.

      Вы создали все требуемые страницы для вашего приложения, используя систему шаблонов Edge. Далее мы настроим и создадим подключение к базе данных нашего приложения.

      Шаг 3 — Создание схемы баз данных

      Если мы запустим приложение сейчас, оно выдаст ошибку, поскольку мы не подключили его к базе данных. В этом разделе мы настроим подключение к базе данных, а затем используем команду adonis для генерирования файла миграции, который будет использоваться для создания таблиц для нее.

      В комплект AdonisJs входит модель ORM под названием Lucid ORM, обеспечивающая реализацию активных записей для работы с базой данных. Эта модель избавляет от необходимости писать запросы SQL, извлекающие данные из базы данных в реальном времени. Это особенно полезно при работе над сложными приложениями, для которых требуется большое количество запросов. Например, мы можем получить все цитаты из нашего приложения с помощью следующей команды:

      const quotes = await Quote.all()
      

      Чтобы продолжить настройку базы данных приложения, необходимо убедиться, что вы все еще находитесь в корневой директории вашего приложения, и создать в ней файл .env:

      Откройте созданный файл и добавьте в него следующее содержание:

      .env

      HOST=127.0.0.1
      PORT=3333
      NODE_ENV=development
      APP_URL=http://${HOST}:${PORT}
      CACHE_VIEWS=false
      APP_KEY=bTVOEgUvmTCfkvgrK8gEBC3Qxt1xSYr0
      DB_CONNECTION=mysql
      DB_HOST=127.0.0.1
      DB_PORT=3306
      DB_USER=sammy
      DB_PASSWORD=password
      DB_DATABASE=adonis
      SESSION_DRIVER=cookie
      HASH_DRIVER=bcrypt
      

      По умолчанию для подключения приложений AdonisJs к базе данных используется СУБД SQLite, которую мы здесь заменим на MySQL. Также мы укажем PORT для приложения, среду приложения и учетные данные для входа в базу данных. Замените DB_USER, DB_PASSWORD и DB_DATABASE своими учетными данными для базы данных.

      Далее мы создадим модель и файл миграции для Quote, используя Adonis CLI. Для этого нужно запустить следующую команду:

      • adonis make:model Quote --migration

      Результат будет выглядеть примерно так:

      Output

      ✔ create app/Models/Quote.js ✔ create database/migrations/1568209992854_quote_schema.js

      Эта команда создаст модель Quote в папке app/Models и файл схемы в папке database/migrations. Созданный файл схемы будет иметь префикс с указанием текущей временной метки. Откройте файл схемы с помощью следующей команды:

      • nano database/migrations/1568209992854_quote_schema.js

      Обновите его содержимое с помощью следующего кода:

      database/migrations/…quote_schema.js

      'use strict'
      /** @type {import('@adonisjs/lucid/src/Schema')} */
      const Schema = use('Schema')
      class QuoteSchema extends Schema {
        up () {
          this.create('quotes', (table) => {
            table.increments()
            table.integer('user_id').notNullable()
            table.string('username', 80).notNullable()
            table.string('body').notNullable()
            table.timestamps()
          })
        }
        down () {
          this.drop('quotes')
        }
      }
      module.exports = QuoteSchema
      

      Для файла схемы в AdonisJs требуются два разных метода:

      • up: используется для создания новых таблиц и изменения существующих.
      • down: используется для отмены изменений, примененных с помощью метода up.

      В дополнение к полям timestamps() и increments() мы обновим содержание файла схемы, указав атрибуты полей user_id, username и body для создаваемой цитаты. В полях user_id и username указываются данные пользователя, создавшего определенную цитату. Файл построен по принципу отношения одного к многим. Это означает, что пользователю может принадлежать бесконечное количество цитат, а цитата может принадлежать только одному пользователю.

      Сохраните и закройте файл.

      В AdonisJs по умолчанию установлены модель User и ее файл миграции. В связи с этим требуется лишь небольшое изменение для установки отношения между моделями User и Quote.

      Откройте модель User в app/Models/User.js:

      Добавьте этот метод сразу же после метода tokens():

      app/Models/User.js

      ...
      class User extends Model {
        ...
        tokens () {
          return this.hasMany('App/Models/Token')
        }
      
        quote () {
          return this.hasMany('App/Models/Quote')
        }
      }
      
      module.exports = User
      

      Эта команда устанавливает отношение «один ко многим» с таблицей Quote, используя user_id как посторонний ключ.

      Сохраните и закройте файл.

      В завершение этого раздела мы используем для проведения миграции следующую команду, которая выполнит метод up() для всех файлов миграции:

      Вы увидите примерно следующий результат:

      Output

      migrate: 1503248427885_user.js migrate: 1503248427886_token.js migrate: 1568209992854_quote_schema.js Database migrated successfully in 3.42 s

      Мы настроили и защитили соединение с базой данных. Также мы создали модель Quote и соответствующий файл схемы и создали отношение один ко многим между моделями User и Quote. Далее мы сгенерирурем маршруты и создадим контроллеры для обработки запросов HTTP и бизнес-логики для создания, изменения и удаления вдохновляющей цитаты.

      Шаг 4 — Создание контроллеров и настройка маршрутов

      В этом разделе мы начнем с создания контроллеров для обработки всей логики приложения, а затем прикрепим эти контроллеры к определенному маршруту, чтобы пользователи могли использовать URL-адрес для получения доступа к ним.

      Для начала мы используем Adonis CLI для создания нового контроллера запросов HTTP для обработки всех процессов аутентификации нашего приложения, выполнив следующую команду:

      • adonis make:controller Auth --type http

      Эта команда создаст файл AuthController.js и сохранит его в папке app/Controllers/Http. Используйте флаг --type, чтобы указать, что этот контроллер должен быть контроллером HTTP.

      Вы увидите примерно следующий результат:

      Output

      ✔ create app/Controllers/Http/AuthController.js

      Затем откройте созданный файл контроллера:

      • nano app/Controllers/Http/AuthController.js

      Добавьте в него следующее содержание:

      app/Controllers/Http/AuthController.js

      'use strict'
      const User = use('App/Models/User')
      class AuthController {
      
          loginView({ view }) {
              return view.render('auth.login')
          }
          registrationView({ view }) {
              return view.render('auth.register')
          }
      
          async postLogin({ request, auth, response}) {
              await auth.attempt(request.input('email'), request.input('password'))
              return response.route('index')
          }
      
          async postRegister({ request, session, response }) {
              const user = await User.create({
                  username: request.input('name'),
                  email: request.input('email'),
                  password: request.input('password')
              })
              session.flash({ successmessage: 'User have been created successfully'})
              return response.route('login.create');
          }
      
          async logout ({ auth, response }) {
              await auth.logout()
              return response.route("https://www.digitalocean.com/")
          }
      }
      module.exports = AuthController
      

      В этом файле мы импортируем модель User и создаем два метода с именами loginView() и registerView() для рендеринга страниц входа в систему и регистрации соответственно. В заключение мы создадим следующие асинхронные методы:

      • postLogin(): этот метод получает значения email и password, опубликованные посредством встроенного метода request в AdonisJs, а затем сверяет эти учетные данные пользователя с базой данных. Если такой пользователь существует в базе данных и ввел правильные учетные данные, пользователь возвращается на главную страницу как прошедший аутентификацию и может создать новую цитату. В ином случае появится сообщение о том, что учетные данные введены неверно.
      • postRegister(): этот метод получает значения username, email и password для создания учетной записи пользователя в базе данных. В сеанс приложения передается сообщение об успешном создании пользователя, а пользователь перенаправляется на страницу входа в систему для прохождения аутентификации, после чего он может создать цитату.
      • logout(): этот метод выполняет функцию выхода из системы и возвращает пользователя на главную страницу.

      Сохраните и закройте файл.

      Мы настроили контроллер для регистрации и аутентификации пользователей. Теперь мы создадим контроллер запросов HTTP для управления всеми операциями с цитатами.

      Вернитесь в терминал и запустите следующую команду для создания контроллера QuoteController:

      • adonis make:controller Quote --type http --resource

      Используйте флаг --resource для создания контроллера с заданными методами ресурсов для операций создания, чтения, обновления и удаления (CRUD).

      Вы увидите следующее:

      Output

      ✔ create app/Controllers/Http/QuoteController.js

      Найдите этот файл в папке app/Controllers/Http/QuoteController.js:

      • nano app/Controllers/Http/QuoteController.js

      Добавьте в него следующее содержание:

      app/Controllers/Http/QuoteController.js

      'use strict'
      const Quote = use('App/Models/Quote')
      
      class QuoteController {
      
        async index ({ view }) {
          const quote = await Quote.all()
          return view.render('index', {
            quotes: quote.toJSON()
          })
        }
      
        async create ({ view }) {
          return view.render('quotes.create-quote')
        }
      
        async store ({ request,auth,session, response }) {
          const quote = await Quote.create({
            user_id: auth.user.id,
            username: auth.user.username,
            body: request.input('body')
          })
          session.flash({ 'successmessage': 'Quote has been created'})
          return response.redirect("https://www.digitalocean.com/")
        }
      
        async show ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.view-quote', {
            quote: quote.toJSON()
          })
        }
      
        async edit ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.edit-quote', {
            quote: quote.toJSON()
          })
        }
      
        async update ({ params, request, response, session }) {
          const quote = await Quote.find(params.id)
          quote.body = request.input('body')
          await quote.save()
          session.flash({'successmessage': 'Quote has been updated'})
          return response.redirect("https://www.digitalocean.com/")
        }
      
        async destroy ({ params, response, session }) {
          const quote = await Quote.find(params.id)
          await quote.delete()
          session.flash({'successmessage': 'Quote has been deleted'})
          return response.redirect("https://www.digitalocean.com/")
        }
      }
      module.exports = QuoteController
      

      В этом контроллере мы импортировали модель Quote и обновили следующие методы, которые были автоматически созданы с помощью AdonisJs CLI:

      • index(): доставка всех цитат из базы данных и их рендеринг на главной странице приложения.
      • create(): рендеринг страницы для создания цитат.
      • store(): сохранение созданной цитаты в базе данных и вывод соответствующего ответа.
      • show(): получение идентификатора определенной цитаты, ее извлечение из базы данных и рендеринг на странице редактирования цитаты.
      • edit(): получение деталей определенной цитаты из базы данных и ее рендеринг для редактирования.
      • update(): обработка любых изменений цитаты и возвращение пользователя на главную страницу.
      • destroy(): удаление определенной цитаты и ее полное удаление из базы данных.

      Сохраните и закройте файл.

      После создания всех необходимых контроллеров для этого приложения мы можем настроить маршруты, чтобы пользователи могли легко взаимодействовать с приложением. Для начала перейдите в файл start/routes.js.

      Замените его содержание на следующее:

      start/routes.js

      'use strict'
      const Route = use('Route')
      
      Route.get("https://www.digitalocean.com/",'QuoteController.index').as('index')
      Route.get('/register','AuthController.registrationView').as('register.create')
      Route.post('/register-store','AuthController.postRegister').as('register.store').validator('Register')
      Route.get('/login','AuthController.loginView').as('login.create')
      Route.post('/login-store','AuthController.postLogin').as('login.store')
      Route.get('/view-quote/:id','QuoteController.show').as('view.quote')
      
      Route.group(() => {
          Route.get('/create-quote','QuoteController.create').as('create.quote')
          Route.post('/store-quote','QuoteController.store').as('store.quote')
          Route.get('/edit-quote/:id','QuoteController.edit').as('edit.quote')
          Route.post('/update-quote/:id','QuoteController.update').as('update.quote')
          Route.get('/delete-quote/:id','QuoteController.destroy').as('delete.quote')
          Route.post('/logout','AuthController.logout').as('logout')
      }).middleware(['auth'])
      

      Здесь мы определяем путь к каждому маршруту нашего приложения, задаем глаголы HTTP для каждого действия и привязываем маршрут к определенному методу в каждом контроллере. Также мы присвоим имена каждому из маршрутов, поскольку контроллеры и представления ссылаются на них.

      Чтобы обеспечить доступ ко всем маршрутам цитат только для пользователей, прошедших аутентификацию, мы назначим соответствующую группу middleware. В заключение мы прикрепим метод проверки к маршруту register.store для проверки вводимых пользователем данных.

      Сохраните и закройте файл.

      Мы создали контроллеры и настроили маршруты приложения. Далее мы создадим метод проверки, определяемый на этом шаге.

      Шаг 5 — Проверка вводимых пользователем данных

      AdonisJs не имеет встроенных по умолчанию средств проверки. Поэтому средство проверки для вашего приложения нужно установить и зарегистрировать вручную.

      Запустите следующую команду для его установки:

      Откройте следующий файл для регистрации поставщика средства проверки:

      Зарегистрируйте поставщика средства проверки, добавив его в список поставщиков, как показано далее:

      start/app.js

      ...
      const providers = [
         ...
         '@adonisjs/cors/providers/CorsProvider',
         '@adonisjs/shield/providers/ShieldProvider',
         '@adonisjs/session/providers/SessionProvider',
         '@adonisjs/auth/providers/AuthProvider',
         '@adonisjs/validator/providers/ValidatorProvider'
      ]
      

      Мы установили и зарегистрировали поставщика средства проверки в нашем приложении. Теперь мы создадим собственное средство проверки ввода данных пользователем при регистрации с помощью следующей команды:

      • adonis make:validator Register

      Эта команда создаст файл Register.js в директории App/validators. Откройте файл с помощью следующей команды:

      • nano app/Validators/Register.js

      Добавьте в файл следующий код:

      app/Validators/Register.js

      'use strict'
      class Register {
        get rules () {
          return {
            name:'required',
            email:'required|email|unique:users',
            password:'required|min:8'
          }
        }
      
        get messages(){
          return{
            'name.required':'Full name is required',
            'email.required':'email is required',
            'email.unique':'email already exists',
            'password.required':'password is required',
            'password.min':'password should be at least 8 characters'
          }
        }
      }
      module.exports = Register
      

      Для определенных полей в приложении можно определять правила. Если проверка не будет пройдена на любом этапе, средство проверки автоматически выведет всплывающее сообщение об ошибке и возвратит пользователя в форму.

      Сохраните и закройте файл после завершения редактирования.

      Для добавление стилей в ваше приложение откройте следующий файл:

      Замените его содержание на следующее:

      /public/style.css

      @import url('https://fonts.googleapis.com/css?family=Montserrat:300');
      
      html, body {
        height: 100%;
        width: 100%;
      }
      
      body {
        font-family: 'Montserrat', sans-serif;
        font-weight: 300;
        background-image: url("/splash.png");
        background-color: #220052;
      }
      
      * {
        margin: 0;
        padding: 0;
      }
      
      a {
        color: inherit;
        text-decoration: underline;
      }
      
      p {
        margin: 0.83rem 0;
      }
      
      .quote-wrapper {
        margin-top: 20px;
      }
      
      .quote-wrapper a {
        text-decoration: none;
      }
      
      .quote-wrapper a:hover {
        color: #ffffff;
      }
      
      .empty-quote {
        color: #ffffff;
      }
      
      form {
        padding: 20px;
      }
      

      В этом файле мы обновляем стили CSS нашего приложения в файле style.css.

      Мы установили и зарегистрировали поставщика средства проверки с целью проверки данных, вводимых пользователями при регистрации. Также мы обновили содержание таблицы стилей, добавив в приложение дополнительные стили. На последнем шаге мы проведем тестирование нашего приложения.

      Шаг 6 — Выполнение приложения

      На этом шаге мы запустим наше приложение и создадим пользователя и пароль для тестирования аутентификации. Также мы добавим в приложение цитату и просмотрим ее на главной странице.

      Чтобы протестировать приложение, запустите сервер разработки, выполнив следующую команду в корневой директории вашего приложения:

      Приложение будет запущено на порту, заданном в файле root .env, а именно на порту 3333. Откройте в браузере адрес http://localhost:3333.

      Главная страница приложения с цитатами

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

      Страница регистрации

      Введите свои данные и нажмите кнопку Отправить, чтобы завершить процедуру регистрации. Вы будете перенаправлены на страницу входа. Введите свой адрес электронной почты и пароль для аутентификации.

      Страница входа

      После аутентификации нажмите кнопку Создать цитату.

      Страница создания цитаты

      Введите цитату и перейдите на страницу Показать все для ее просмотра.

      Страница просмотра всех цитат

      Мы протестировали приложение, создав пользователя, пройдя аутентификацию и написав цитату.

      Заключение

      В этом обучающем руководстве мы создали веб-приложение с помощью AdonisJs. Мы настроили приложение с помощью AdonisJs CLI и использовали CLI для создания других важных файлов, в том числе контроллеров, моделей и представлений.

      В этой инфраструктуре вы можете создавать веб-приложения любого размера и сложности. Исходный код проекта можно загрузить на GitHub здесь. Дополнительную информацию можно найти в официальной документации.

      Если вы хотите посмотреть наши другие обучающие руководства по инфраструктуре JavaScript, обратите внимание на следующие:



      Source link