[Перевод] Remix: руководство по новому open source React-фреймворку
Последнее время кажется, что React-фреймворки выходят каждый день. Хотя каждому из них есть, что предложить, Remix особенно выделяется. Cам по себе он не новый, но в опенсорс перешел совсем недавно. Изначально он был доступен только по платной подписке.
Remix — React-фреймворк для SSR (server-side rendering). Это означает, что бэкенд и фронтенд реализуются в одном приложении. Рендер происходит на сервере и верстка передается на клиент с минимальным использованием JavaScript. В классическом React-приложении данные сначала отдельно фетчатся, а затем компоненты с ними рендерятся на фронте. Remix, напротив, получает данные на бэкенде и передает отрендеренный HTML напрямую пользователю.
В этой статье мы поговорим про некоторые удобные особенности Remix и создадим с его помощью приложение с погодой. В конце я поделюсь своими личными взглядами на Remix и расскажу, буду ли использовать его в своих будущих проектах.
Что будет в статье:
Плюсы использования Remix
Remix, как и остальные фреймворки, имеет несколько особенностей «из коробки», которые делают его удобным для разработчиков. Вот некоторые, которые нравятся мне.
Вложенные страницы
Любая страница внутри папки какого-либо роута является вложенным роутом, а не отдельным. Поэтому вы можете вставить эти компоненты внутрь вашей родительской страницы, что сокращает время загрузки.
Еще одно преимущество: для этих вложенных страниц мы можем установить Error Boundary, что поможет с обработкой ошибок в конкретных компонентах.
Error Boundaries
Допустим, вы получили ошибку в Remix-компоненте или вложенном роуте. Ошибки ограничены компонентом, и он либо не отобразится, либо просто покажет ошибку. В других фреймворках это сломает всю страницу, и вы увидите целый экран с ошибкой.
Error Boundaries могут быть реализованы в Next.js, но в Remix они встроены «из коробки». Мне кажется, что это очень удобно для продакшн-сборки, чтобы пользователь не получил блокировку целой страницы из-за простой ошибки.
Переходы
Remix автоматически обрабатывает все состояния загрузки за вас. Все, что нужно сделать — сказать, что нужно показывать во время загрузки приложения. Во фреймворках вроде Next.js вам понадобится установить состояние загрузки с помощью какой-нибудь библиотеки управления состоянием — например Redux или Recoil. То есть на других фреймворках для этого вам нужны дополнительные действия, а в Remix это встроенная возможность.
Традиционные формы
Вернемся в то время, когда разработчики пользовались PHP. Тогда использовался метод отправки формы и action с URLом. В Remix похожий подход.
Я понимаю, что это звучит не очень круто, все привыкли к onClick
, onSubmit
и HTTP-запросам. Но Remix обрабатывает формы совершенно по-другому. Здесь у вас есть функции вроде action
или loader
для выполнения server-side-операций. Данные формы доступны в этих функциях в момент исполнения на сервере, поэтому для ее отправки вообще не нужен JS на фронтенде.
Допустим, у вас есть простой веб-сайт и вам даже не нужен JS на фронте. В этом случае лучше всего сработает классическая отправка формы. В других фреймворках вам придется вызывать fetch
или axios
, но не в Remix. Это может сильно упростить жизнь.
Недостатки Remix
Хотя Remix имеет много плюсов, некоторые нюансы могут заставить задуматься перед его использованием.
Малое сообщество
Remix лишь недавно заопенсорсили, и пока что в проектах его используют немногие.
Поэтому когда вы столкнетесь с проблемами, найти решение в интернете может оказаться сложно.
Непрозрачная система роутинга
Когда я начинал работать с Remix, система маршрутизации меня немного смутила. Я не мог разобраться в концепции вложенных роутов. Пришлось использовать другие фреймворки без этой специфической системы. Поэтому порог входа у Remix чуть выше.
Чем Remix отличается от Next.js?
На первый взгляд, разница небольшая, потому что оба они поддерживают SSR. Однако Next.js поддерживает еще и SSG (Static Site Generation), а Remix фокусируется только на SSR.
Проектируем простое приложение на Remix
Мы рассмотрели некоторые преимущества Remix. Настало время сделать с его помощью простое приложение с погодой.
Начальные требования:
установленный Node.js
Visual Studio Code или другая IDE
OpenWeatherMap API ключ — достаточно бесплатного
практическое знание React
Если во время работы у вас возникнут трудности, код доступен на GitHub.
Создание Remix-приложения
В терминале введите команду для создания Remix-проекта:
npx create-remix@latest weather-app
weather-app — название проекта, можете заменить его на любое другое. Нажав Enter
, вы увидите интерактивное меню, которое поможет создать Remix-приложение:
Здесь вам нужно указать, куда деплоить приложение. В этой статье мы только экспериментируем и не касаемся темы деплоя, поэтому просто используем Remix App Server.
После этого нужно указать, что вы будете использовать: JavaScript или TypeScript. Для простоты руководства я буду использовать JS.
Сейчас нужно указать, следует ли Remix использовать npm install
. Нажмите y
. Это установит требуемые зависимости.
Перейдите в директорию проекта и используйте следующую команду для установки некоторых зависимостей, которые понадобятся в этом проекте:
npm install axios dotenv
axios
нужен, чтобы можно было отправить HTTP-запрос к API OpenWeatherMap. dotenv
мы будем использовать для сохранения API-ключа в переменной окружения.
Теперь давайте отредактируем package.json
, чтобы использовать переменные окружения в режиме разработки в Remix. Замените скрипт dev
на следующий:
"dev": "node -r dotenv/config node_modules/.bin/remix dev"
Это включит возможность использования переменных окружения в вашем проекте. Теперь создайте новый .env
-файл для наших переменных окружения и сохраните API-ключ в следующем формате:
WEATHER_API_KEY={api key here}
Посмотрим на структуру каталога Remix:
Каталог app
содержит логику нашего основного приложения. Все файлы и папки в каталоге routes
публичны и доступны по URL. Каталог styles
содержит все CSS-файлы по аналогии с роутами.
entry.client.jsx
и entry.server.jsx
управляются через Remix, и эти файлы лучше не трогать. Вместо этого создайте новые файлы и работайте с ними. Файл root.jsx
содержит макет нашей общей страницы.
Каталог public
содержит статику — изображения, иконки.
Файл remix.config.js
содержит базовую конфигурацию нашего приложения Remix, например порт для запуска в режиме разработки.
Очистка
Когда вы впервые настраиваете Remix-приложение, в нем уже есть несколько туториалов и демок. Первым делом удалим их, чтобы можно было поработать над нашим приложением.
Откройте root.jsx
и очистите встроенный компонент Layout
, чтобы он выглядел так:
function Layout({ children }) {
return {children};
}
Перейдите в каталог styles
, удалите папку demos
и очистите содержимое dark.css
и global.css
. Это очистит все стили.
Удалите папку demos
также в директории routes
, потому что нам она не нужна.
Переходите к index.jsx
и очистите все. Просто убедитесь, что у вас по умолчанию экспортируется компонент Index:
export default function Index() {
return ;
}
Создание формы и получение погоды
Давайте создадим форму в index.jsx
со следующей разметкой:
export default function Index() {
return (
);
}
Выше мы создали форму с методом get
. У инпута есть имя, которое станет query-параметром в URL после отправки формы.
Теперь посмотрим, как пользоваться вложением маршрутов. Создайте файл weather.jsx
в папке routes
. Он будет обрабатывать урл/weather
.
import { Outlet } from "react-router";
export default function Weather() {
return (
<>
Weather App
>
);
}
Компонент Outlet
будет искать папку weather
внутри routes
и вставлять страницы в основную страницу. Возможно, это поможет вам понять, как работает вложение страниц в Remix.
Теперь создайте папку weather
в routes
и внутри нее новый файл index.jsx
. Давайте напишем функцию loader
, которая запустится на стороне сервера, независимо от того, где запросили страницу:
export async function loader({ request }) {
try {
const url = new URL(request.url);
const search = new URLSearchParams(url.search);
if (!search.get("city")) return redirect("/");
const city = search.get("city");
const res = await axios.get(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.WEATHER_API_KEY}&units=metric`
);
console.log(res.data);
return { city, type: res.data.weather[0].main, temp: res.data.main.temp };
} catch (err) {
console.error(err);
redirect("/");
return {};
}
}
Выше мы извлекли название города из query-параметров URL. Затем сделали запрос к API OpenWeatherMap, чтобы получить погоду в этом городе. Теперь нам нужно вернуть данные на фронтенд, чтобы они были доступны для рендеринга.
Теперь давайте поработаем над компонентом финального экрана:
export default function Index() {
const data = useLoaderData();
return (
{data.city}
{data.type}
Temperature: {data.temp} °C
);
}
Хук useLoaderData
получает данные, которые были возвращены с использованием функции loader
. Если вы все сделали правильно, погода должна отобразиться примерно так:
Поздравляю! Вы сделали первое приложение с использованием Remix!
Заключение
Я думаю, что Remix — мощная технология, которая должна набирать популярность в 2022.
Буду ли я использовать ее вместо Next.js? Может, и нет: у Next.js есть большое сообщество, в отличие от Remix, который только-только перешел в open source.
Это не значит, что мне не нравится этот фреймворк. Я могу использовать его для своих личных проектов. Я хочу еще поэкспериментировать с Error Boundaries.
Но на мой взгляд, сейчас более предпочтителен Next.js. Чтобы найти в Интернете некоторые проблемы, с которыми я столкнулся в Remix, пришлось потрудиться. Возможно, через несколько лет все изменится, и Remix станет более мощным фреймворком с большой поддержкой сообщества.
А вам интересно попробовать Remix?