Больше не нужно искать работу мечты — присоединяйтесь к команде Клауда

Как создать и развернуть приложение на Next.js: быстрый и простой деплой с Apps

Сергей Дурманов
Сергей Дурманов
Технический писатель
23 октября 2024 г.
10
14 минут чтения
Средний рейтинг статьи: 5

Сегодня мы с вами научимся создавать приложение на Next.js для фильтрации новостей («Мои новости»). Next.js — это современный фреймворк для React, который упрощает разработку веб-приложений благодаря встроенной поддержке серверного рендеринга и статической генерации, оптимизирует производительность и SEO (страница генерируется на сервере и отправляется пользователю в готовом виде, в том числе, например, с уже заполненными данными из базы данных. Это означает, что поисковые системы могут легко индексировать страницу, а пользователи видят контент быстрее).

Нам потребуется около 5 минут для разбора кода и еще 5 минут — для развертывания приложения на сервисе Timeweb Cloud Apps, после чего мы получим:

  • Готовый URL для приложения.
  • Готовое приложение фильтрации новостей.
  • Научимся сохранять настройки приложения в вашем браузерном хранилище.
  • Научимся обращаться с запросами в интернет, минуя CORS-ограничения.
  • Сможем подключать разные источники новостей.

Вот так будет выглядеть ваше приложение.  

Nextjs 01

Правда, неплохо? А теперь давайте сделаем ваш личный вариант поиска новостей, который вы сможете регулировать и настраивать самостоятельно.

Что нам потребуется

  • Зарегистрированный аккаунт на Github, Gitlab или Bitbucket.
  • Зарегистрированный аккаунт на платформе Timeweb Cloud.
  • Глубокое знание фреймворка Next.js не обязательно, так как вся бизнес-логика написана на JavaScript.

Кейсы: кому и как использовать Next.js + Timeweb Cloud Apps

  1. Web-разработчикам одностраничных сайтов, для которых важен SEO и статическая генерация страниц.
  2. Разработчикам корпоративных систем для быстрой разработки активных прототипов и макетов.
  3. Разработчикам API-систем для очень быстрой разработки действующих прототипов.
  4. Всем, кто использует cloud function и edge function, для организации сложных перекрестных запросов к БД или другим источникам, агрегирования и выдачи форматированного ответа, либо запуска удаленных webhook.
  5. Студентам и школьникам для создания интерактивных презентаций.

Итак, приступим…

Деплой приложения на Next.js

В данной инструкции мы рассмотрим деплой приложения с использованием Github. Мы подготовили для вас готовое приложение (фильтр новостей) для демонстрации простоты деплоя Next.js-приложений на наш сервис Timeweb Cloud Apps.  Итак, приступим.

Шаг 1: Копирование шаблона

Откройте в браузере страницу репозитория с шаблоном нашего подготовленного приложения и нажмите кнопку «Fork», чтобы скопировать его в свой аккаунт Github.

Nextjs 02

Сохраните репозиторий в своем аккаунте. Название репозитория можете оставить таким же.

Шаг 2: Деплой приложения

Для автоматического развертывания статических приложений, созданных с использованием Next.js, Svelte, Vue и других фреймворков, компания Timeweb Cloud создала простой и удобный инструмент Timeweb Cloud Apps. С его помощью Next.js-приложение автоматически собирается и публикуется с созданием публичного URL-адреса.

Этот сервис фактически упрощает процесс, заменяя традиционные системы CI/CD, включая и деплой Next.js с использованием Github.

Развернуть его можно всего в несколько кликов. При изменениях в коде на вашем локальном компьютере система автоматически обнаружит новые коммиты в Github, пересоберет приложение и обновит его на сайте. Чтобы это работало, при первом деплое достаточно выбрать опцию «Сборка по последнему коммиту» (см. скриншоты ниже).

Итак, вам не нужно настраивать свои серверы, чтобы показать работу заказчику. Всего за 1 руб. в месяц, мы:

  • сделаем деплой вашего кода на наш сервер;
  • предоставим вам готовый рабочий домен;
  • попросим всего лишь 5-10 минут вашего внимания.

Поскольку вы уже зарегистрированы в Timeweb Cloud, просто перейдите в панели управления в раздел «Apps» → «Создать» и выберите тип приложения «Next.js» и версию Node.js по желанию.

Nextjs 03

Теперь вам нужно подключить свой GitHub-аккаунт, чтобы платформа могла отслеживать изменения в проекте и автоматически запускать деплой. Дополнительные настройки не требуются — просто нажмите кнопку «Подключить аккаунт» и выберите ваш репозиторий в Github.

Nextjs 05

Во время подключения вам будет предложено окно авторизации GitHub. Введите свой код авторизации и нажмите кнопку «Подтвердить». Также убедитесь, что переключатель установлен на «Сборка по последнему коммиту».

Image12

После авторизации, выберите репозиторий, который вы форкнули (скопировали) к себе в аккаунт и нажмите кнопку «Save».

Nextjs 04

Вы успешно выполнили два необходимых шага. Теперь нажимайте кнопку «Запустить деплой» (стрелка 3) и наслаждайтесь.

Nextjs 05

Платформа Timeweb Cloud Apps на ваших глазах соберет приложение, покажет вам весь процесс компиляции приложения и деплоя на сервер.

Nextjs 06

Поздравляем! Ваше приложение Next.js успешно размещено c в сервисе Timeweb Cloud Apps, и теперь вы можете использовать его без необходимости настройки хостинга. Перейдите в настройки, скопируйте публичный URL и откройте приложение в браузере. Вы также можете изменить адрес на свой собственный, используя кнопку «Редактировать». Затем скопируйте сформированный публичный URL и переходите в браузер.

Image1

Как устроено приложение на Next.js

Теперь разберем подробнее, как устроено и работает наше приложение.

Внешний вид и функционал

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

Image3

Исследовав код данного приложения на Next.js, вы научитесь:

  1. Обходить CORS ограничения при запросе к страницам других сайтов;
  2. Сохранять настройки приложения в локальное хранилище браузера;
  3. Парсить текст в DOM-модели страницы и раскрашивать текст.

Подготовка для локальной разработки

Поскольку вы уже скопировали (форкнули) наше приложение в свой репозиторий, теперь мы можем разобраться, из чего оно состоит и как его доработать.

Откройте терминал (для Windows это может быть PowerShell, Windows Terminal или Putty; подробности можно найти в статье). Затем перейдите в папку, где вы храните свои разработки:

cd "/путь/к/папке" 

Клонируйте ваше Next.js-приложение на локальный компьютер:

git clone https://github.com/ВАШ_НИК/nextjs-rss-news-filter.git nextjs-rss-news-filter
cd nextjs-rss-news-filter

Установите зависимости:

npm install

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

npm run dev

Nextjs 09

Откройте ваш трекер в браузере по адресу: http://localhost:3000/.

Исходники приложения

Структура файлов

Откройте редактор или IDE (например VS Code или Zed) и загрузите ваш проект. Структура каталогов вашего приложения выглядит следующим образом:

Nextjs 10

Основной каталог, содержащий логику приложения, — это App. Назначение остальных: 

  • /api/rss/route.js — это ваш серверный код, который принимает запросы от приложения и отдает ответы. В нашем случае он получает просьбу предоставить код RSS-ленты, затем идет на внешний сервер, получает эту ленту и отдает приложению. Именно благодаря такому механизму вы спокойно обходите ограничения CORS и можете спокойно получать и RSS, и страницы других сайтов (например, для парсинга), и запросы к закрытым API.
  • /fonts — шрифты, используемые в приложении.
  • /styles — набор стилей.
  • layout.js — базовый шаблон (скелет) страницы. Здесь вы можете внедрить меню, footer и т.д., которые будут использоваться на всех страницах вашего приложения.
  • page.js — тело главной страницы (у нас одностраничное приложение, поэтому других файлов не будет).

Давайте рассмотрим основной файл page.js и разберем логику (магию) фильтрации новостей по вашему вкусу.

Nextjs 11

Файл состоит из одного блока export default function Home(), который содержит внутри наши функции бизнес-логики, а также шаблон отрисовки страницы.

Перечень методов

Для работы с мы будем использовать всего 10 функций, которые создают 100% магии нашего приложения на Next.js.

Вложенные функции (методы) и их назначение:

Функция

Назначение

filterWordsArray

Преобразование строки с ключевыми словами для поиска в массив

localStorage.getItem

При монтировании загружаем данные из localStorage

localStorage.setItem

Сохраняем данные в localStorage при каждом изменении filterWords

fetchRssFeed

Загрузка RSS-ленты

блок useEffect (строка 60)

Фильтрация новостей по ключевым словам

handleFilterChange

Обработчик изменения текста в textarea

toggleVisibility

Показать/скрыть новость при клике по заголовку

highlightText, highlightedTitle, highlightedDescription, highlightedCategory

Подсветка найденного текста, заголовка, описания, категории

return

Возвращает готовый рендер страницы по HTML-шаблону 

Функции localStorage 

Функции localStorage.getItem и localStorage.setItem предельно просты. Они просто читают или записывают список ваших поисковых слов в хранилище браузера. На них мы не будем останавливаться.

Функции filterWordsArray 

Функция filterWordsArray — это код JavaScript, который просто переводит ваши поисковые слова в массив и удаляет пустые строки с помощью filter(Boolean).

Тело функции:

const filterWordsArray = filterWords
	.split('\n')
	.map((word) => word.trim().toLowerCase())
	.filter(Boolean);

Функция fetchRssFeed

Это наша основная функция. Здесь мы обращаемся к нашему локальному прокси-серверу /api/rss, который в свою очередь идет в интернет, получает реальную RSS-ленту и отдает нашему приложению. Если вы обратитесь к внешней ленте напрямую, то в 90% случаев получите ограничение CORS, а наш механизм позволяет не обращать внимание на такие мелочи (ведь мы же умные разработчики, нас такое не остановит).

Тело функции:

const response = await axios.get('/api/rss');

Получаем ленту

const parser = new DOMParser();

const xml = parser.parseFromString(response.data, 'application/xml');

Преобразуем ленту (это просто набор текста xml) в DOM-модель, которую понимает браузер, и в которой мы можем манипулировать элементами

const items = Array.from(xml.querySelectorAll('item')).map((item) => ({

        title: item.querySelector('title').textContent,

        link: item.querySelector('link').textContent,

        pubDate: item.querySelector('pubDate').textContent,

        description: item.querySelector('description')?.textContent || 'Нет описания',

        category: item.querySelector('category')?.textContent || 'Без категории',

      }));

Что делаем:

Из DOM-документа извлекаются все элементы <item> с помощью querySelectorAll, которые затем преобразуются в массив. Для каждого элемента <item> извлекаются необходимые данные: title, link, pubDate, description, и category. Если description или category отсутствуют, устанавливаются значения по умолчанию.

Все. Теперь мы можем спокойно работать с массивом данных.

setRssItems(items); setShowMessage(true); // Показать сообщение "обновлено" setTimeout(() => setShowMessage(false), 2000); // Скрыть через 2 секунды

Обновляем состояние:

Состояние rssItems обновляется новым массивом элементов. Также отображается сообщение о том, что данные обновлены, и через 2 секунды сообщение скрывается с помощью setTimeout.

} catch (err) {

  setError('Не удалось загрузить RSS ленту');

}

В случае ошибки при выполнении запроса или парсинга, в состояние error записывается сообщение об ошибке.

finally {

  setLoading(false);

}

Блок finally выполняется в любом случае, независимо от того, была ли ошибка или нет. Здесь состояние loading устанавливается в false, указывая на завершение процесса загрузки.

Блок useEffect (строка 60)

Здесь мы обрабатываем текст, очищаем, фильтруем и т.д.

Проверка наличия фильтруемых слов (filterWords)

Если переменная filterWords содержит данные, выполняется дальнейшая фильтрация. Если нет, компонент обновляет состояние всеми элементами rssItems.

Разделение и обработка строк в filterWords

Строка из переменной filterWords разбивается по символу новой строки (\n), создавая массив слов.

Приведение слов к нижнему регистру и удаление лишних пробелов

Каждое слово в массиве обрабатывается с помощью map(), удаляя пробелы и приводя его к нижнему регистру для корректного поиска.

Фильтрация пустых строк

С помощью filter(Boolean) из массива удаляются пустые строки.

Фильтрация RSS элементов на основе ключевых слов

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

Проверка наличия совпадений слов с контентом каждого элемента

Для каждого элемента rssItems, проверяются совпадения слов (с помощью some()) в title, description и category, приведенных к нижнему регистру.

Обновление состояния отфильтрованными элементами

Результаты фильтрации сохраняются в состоянии filteredItems с помощью setFilteredItems(filtered).

Обновление состояния при отсутствии ключевых слов

Если переменная filterWords пустая, в filteredItems сохраняются все элементы из rssItems без фильтрации.

Функция в useEffect динамически фильтрует элементы RSS в зависимости от заданных фильтруемых слов, проверяя их на совпадение в заголовке, описании или категории.

Функции раскрашивая поисковых слов 

Функции highlightText, highlightedTitle, highlightedDescription, highlightedCategory почти идентичны. Они раскрашивают в желтый цвет найденные совпадения. Рассмотрим одну из них.

Тело функции:

const highlightedTitle = (title, words) => {
    const safeWords = words.map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')); // Экранирование спецсимволов
    return <span dangerouslySetInnerHTML={{ __html: highlightText(title, safeWords) }} />;
  };

На входе получаем текст заголовка и список слов для поиска. Сначала делаем экранирование спецсимволов. Каждое слово из массива words обрабатывается с помощью метода replace(). Регулярное выражение /[.*+?^${}()|[\]\\]/g находит все специальные символы, которые нужно экранировать. В результате все специальные символы в строке экранируются, что позволяет безопасно использовать их в регулярных выражениях без изменения их смысла.

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

Встроенный прокси-сервер

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

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

Весь сервер состоит из одного файла и 18 строк кода.

Тело app/api/rss/route.js:

import axios from 'axios';

export async function GET() {
  try {
	// запасной вариант https://lenta.ru/rss/news
	const response = await axios.get('https://www.mk.ru/rss/news/index.xml', {
  	headers: {
    	'Content-Type': 'application/xml',
  	},
	});

	return new Response(response.data, {
  	headers: { 'Content-Type': 'application/xml' },
	});
  } catch (error) {
	return new Response('Ошибка при получении данных', { status: error.response?.status || 500 });
  }
}

Здесь все просто: при вызове функции GET сервер получает из интернета файл https://www.mk.ru/rss/news/index.xml и отдает его содержимое нашему приложению. Вот и вся магия. Зато сколько плюсов.

Заключение

Итак, в данной статье, мы научились создавать среднее по сложности приложение на Next.js и размещать его в публичном пространстве, не создавая собственных серверов и не покупая сложный хостинг.

Для тех, кто только начинает, важно знать, что Next.js — это современный фреймворк для JavaScript, который делает создание веб-приложений намного проще и быстрее. Он помогает приложениям работать быстрее, быть хорошо видимыми в поисковиках и поддерживает как динамическую, так и статическую генерацию страниц. Next.js легко освоить, особенно если вы уже знакомы с React, и он отлично подходит как для новичков, так и для тех, кто хочет разрабатывать приложения на уровне профессионалов.

Timeweb Cloud, в свою очередь, упростит размещение вашего кода в интернете: вы получите удобные и безопасные публичные ссылки на проекты, бесплатные SSL-сертификаты и многое другое. Мы советуем начать с Timeweb Cloud Apps — это идеальная платформа для быстрого старта. 

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

Хотите внести свой вклад?
Участвуйте в нашей контент-программе за
вознаграждение или запросите нужную вам инструкцию
img-server
23 октября 2024 г.
10
14 минут чтения
Средний рейтинг статьи: 5
Пока нет комментариев