Автор: Джозеф Чеге

Strapi — это безголовая CMS с открытым исходным кодом, основанная на Node.js. Он позволяет разрабатывать и управлять любым содержимым вашего приложения. Это позволяет быстрее создавать серверный API с преимуществами эффективности и настраиваемости.

Что такое Ремикс?

С другой стороны, Remix — хороший выбор для использования ваших сгенерированных конечных точек API. Он предлагает загрузку данных на стороне сервера. Remix — это фреймворк для рендеринга на стороне сервера. Это позволяет без проблем работать с сервером и клиентом. Remix очень похож на фреймворк Next.js.

Ремикс против Next.js

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

С введением фреймворков рендеринга на стороне сервера (SSR), таких как Next.js и Remix, страница полностью визуализируется по запросу на сервере. Этот подход подходит для динамического контента, который часто меняется.

Вот некоторые из причин, по которым Remix является хорошим выбором:

  • Это быстрее, чем Next.js.
  • Ремикс имеет лучшую производительность.
  • Remix использует встроенные функции браузера. Это позволяет Remix повторно использовать большинство функций HTML и HTTP на уровне платформы для обработки сложных мутаций. С другой стороны, если приложение Next.js отключается, страница не будет отвечать, что затрудняет обработку мутаций.
  • Ремикс использует собственный HTML и может работать без JavaScript. Это упрощает обработку ошибок на сервере, обеспечивая удобство для пользователя.

Remix и Next.js тесно связаны, и разница между ними минимальна. Ознакомьтесь с этим руководством, чтобы получить более полное представление о том, чем Remix отличается от Next.js.

Предпосылки

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

  • Среда выполнения Node.js, установленная на вашем компьютере,
  • Базовые знания JavaScript и
  • Предыдущий опыт работы с фреймворком на основе React, таким как Remix.

Локальная настройка Strapi

Давайте погрузимся и создадим серверную часть Strapi CMS. Это будет обслуживать сообщения блога для пользователей. Чтобы настроить Strapi CMS, создайте папку проекта. Затем откройте команду, указывающую на этот каталог, желательно с помощью текстового редактора, такого как Visual Studio Code. Выполните следующую команду, чтобы установить Strapi CMS на локальный компьютер:

npx create-strapi-app@latest blog-app

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

Это создаст папку blog-app, в которой будут храниться все файлы проекта и зависимости, которые Strapi CMS потребуется запускать локально. После завершения установки вы будете перенаправлены на страницу администрирования Strapi в браузере по умолчанию http://localhost:1337/admin/auth/register-admin.

Укажите учетные данные для входа в систему администратора Strapi. Если вы еще не создали учетную запись, укажите регистрационные данные. Наконец, нажмите кнопку Начать, чтобы получить доступ к панели администратора.

Создайте коллекцию блогов с помощью Strapi CMS

Здесь мы создаем приложение для блога. Следовательно, нам нужно смоделировать содержимое серверной части приложения для блога с помощью Strapi. Первым шагом является настройка типа контента. В административной панели Strapi нажмите Content-Type Builder.

Затем нажмите кнопку + Создать новый тип коллекции, чтобы настроить коллекцию. Введите blog в качестве имени типа контента:

Нажмите Продолжить и настройте следующие поля блога:

  • Заголовок в виде короткого текста — краткий заголовок для вашего сообщения в блоге.
  • Отрывок в виде длинного текста — краткое изложение вашего сообщения, которое будет отображаться в веб-приложении.
  • Hero: выберите медиафайл, один — описательное изображение для вашего сообщения в блоге.
  • Контент: как форматированный текст — представляет содержание вашего сообщения в блоге.

Наконец, создайте тестовый контент для вышеуказанной коллекции и ее полей. Нажмите кнопку + Создать новую запись:

Заполните все поля, а затем убедитесь, что вы публикуете добавленный контент:

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

Добавление ролей и разрешений

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

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

Чтобы получить доступ к созданной коллекции blog, создайте токен API, который Remix будет использовать для связи со Strapi. Чтобы создать токен:

  • Перейдите в раздел Настройки на панели управления Strapi.
  • Щелкните раздел Токены API.
  • Нажмите кнопку «Создать новый токен API», чтобы установить токен для использования API.

Введите имя и описание в соответствующие поля. Наконец, выберите тип токена Только для чтения и нажмите «Сохранить».

В этом примере Remix будет читать только содержимое нашей коллекции. Если вам нужно добавить такие операции, как запись в Strapi CMS, убедитесь, что вы изменили тип токена соответствующим образом.

Токен API будет сгенерирован. Скопируйте созданный токен, так как мы будем использовать его с Remix.

Настройка приложения Remix

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

npx create-remix@latest remix-blog-app

Приведенная выше команда создаст папку remix-blog-app, в которой будут размещены все файлы проекта и зависимости, которые потребуются Remix для запуска локального веб-приложения.

После завершения установки перейдите во вновь созданный каталог:

cd remix-blog-app

Вы можете проверить, правильно ли работает созданное приложение Remix, запустив:

npm run dev

Откройте http://localhost:3000/ в браузере, и вы увидите приветственную версию веб-приложения Remix.

В корневом каталоге Remix проекта (remix-blog-app) создайте файл .env и добавьте следующие конфигурации Remix:

STRAPI_API_TOKEN="your_access_token"
STRAPI_URL_BASE="http://your_local_ip_address:1337"

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

Настройка компонентов ремикса

Компоненты задают пользовательский интерфейс приложения. Remix использует компоненты для настройки различных разделов веб-приложения. Здесь будут созданы следующие компоненты:

  • Панель навигации: базовая панель навигации веб-приложения.
  • Карточки сообщений в блогах: карточки ремиксов для отображения сообщений и их свойств.
  • Макет: чтобы установить общий макет веб-страницы.

Чтобы настроить эти компоненты, создайте папку components в каталоге app проекта Remix. Внутри папки components создайте следующие файлы и соответствующие блоки кода для создания компонентов:

Navbar.jsx:

export default function Navbar() {
        return (
            <nav className="navbar">
                <div className="nav-wrapper">
                    <a href="/" className="brand-logo">Blog App</a>
                </div>
            </nav>
        )
    }

Здесь мы создаем Navbar, который отображает логотип бренда приложения в виде текста Blog App. Щелчок по этому логотипу бренда перенаправит пользователя на домашнюю страницу приложения.

BlogCard.jsx:

import { Link } from '@remix-run/react';
    import url from '../utils/url';
    
    export default function BlogCard({ blog }) {
        let data = blog.attributes;
        return (
            <div className="card">
                <div className="card-content">
                    <div className="card-img">
                        <img src={`${url}${data.hero.data.attributes.url}`} alt={data.hero.data.attributes.alternativeText} />
                    </div>
                    <div className="card-details">
    
                        <Link to={`/posts/${blog.id}`} className="card-title">
                            {data.title}
                        </Link>
    
                        <p className="card-excerpt">{data.excerpt}</p>
                    </div>
                </div>
            </div>
        )
    }

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

Layout.jsx:

import Navbar from './Navbar';
    
    export default function Layout({ children }) {
        return (
            <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
                <Navbar />
                <div className="container">
                    {children}
                </div>
            </div>
        );
    }

Компонент Layout запускает контейнер, который оборачивает компонент Navbar в основное приложение.

style.css

Чтобы стилизовать вышеуказанные компоненты, добавьте следующий код CSS в файл style.css:

/* Navbar */
    .navbar {
      box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05);
      margin-bottom: 0;
      padding: 12px;
      position: relative;
    }
    
    .navbar .nav-wrapper a {
      text-decoration: none;
      font-size: 20px;
    }
    
    /* Layout */
    .container {
      width: 50%;
      margin: 0px auto;
    }
    
    /* Blog card */
    .card {
      width: 100%;
      padding: 10px;
      margin: 10px 0px;
      border-radius: 5px;
      box-shadow: 0 1px 3px 0 #d4d4d5, 0 0 0 1px #d4d4d5;
    }
    
    .card-content {
      width: 100%;
      display: flex;
      justify-content: space-between;
    }
    
    .card-content .card-img {
      width: 50%;
      height: 100%;
    }
    
    .card-img img {
      width: 90%;
      height: 100%;
      border-radius: 5px;
    }
    
    .card-details .card-title {
      text-decoration: none;
    }

index.jsx:

Чтобы выполнить вышеуказанные компоненты, создайте файл index.jsx и экспортируйте его, как показано в следующем блоке кода:

import BlogCard from "./BlogCard";
    import Layout from "./Layout";
    import Navbar from "./Navbar";
    export { BlogCard, Layout, Navbar };

Экспорт этих компонентов упрощает доступ к ним и их использование другими модулями приложения.

Настройка утилит для ремиксов

Создайте папку utils внутри каталога Remix app. Внутри папки utils создайте следующие файлы:

  • errorHandling.js: Для обработки исключений при подключении к серверному API Strapi:
// Custom error class for errors from Strapi API
    class APIResponseError extends Error {
        constructor(response) {
            super(`API Error Response: ${response.status} ${response.statusText}`);
        }
    }
    
    export const checkStatus = (response) => {
        if (response.ok) {
            // response.status >= 200 && response.status < 300
            return response;
        } else {
            throw new APIResponseError(response);
        }
    }
    
    class MissingEnvironmentVariable extends Error {
        constructor(name) {
            super(`Missing Environment Variable: The ${name} environment variable must be defined`);
        }
    }
    
    export const checkEnvVars = () => {
        const envVars = [
            'STRAPI_URL_BASE',
            'STRAPI_API_TOKEN'
        ];
    
        for (const envVar of envVars) {
            if (!process.env[envVar]) {
                throw new MissingEnvironmentVariable(envVar)
            }
        }
    }
  • url.js: URL-адрес локального хоста хоста Strapi.
export default "http://localhost:1337";

Настройка маршрутов

Чтобы получить доступ к сообщениям, мы создадим маршруты Remix. В этом случае у нас будет два основных маршрута:

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

Давайте создадим эти маршруты.

Получение всех сообщений

Перейдите к файлу app/routes/index.jsx и извлеките все записи блога следующим образом:

  • Импортируйте все необходимые модули:
import { useLoaderData } from '@remix-run/react';
    import { checkEnvVars, checkStatus } from '../utils/errorHandling';
    import {Layout, BlogCard} from '../components';
    import styles from '../components/style.css';
  • Настройте стили для компонента BlogCard:
export const links = () => [
        { rel: "stylesheet", href: styles },
    ];
  • Настройте загрузчик для загрузки сообщений из Strapi:
export async function loader() {
        checkEnvVars(); // check environmental variables
        const response = await fetch(`${process.env.STRAPI_URL_BASE}/api/blogs?populate=hero`, {
            method: "GET",
            headers: {
                "Authorization": `Bearer ${process.env.STRAPI_API_TOKEN}`,
                "Content-Type": "application/json"
            }
        }); // get the blogs
    
        checkStatus(response); // check the status
    
        const data = await response.json(); // get the json response
    
        if (data.error) { // error check
            throw new Response("Error loading data from strapi", { status: 500 });
        }
    
        return data.data; // return the data
    }
  • Отредактируйте функцию рендеринга, чтобы получать сообщения и отображать их в компоненте BlogCard:
export default function Index() {
        const blogs = useLoaderData();
        return (
            <Layout>
                {
                    blogs.length > 0 ? (
                        blogs.map(blog => (
                            <BlogCard key={blog.id} blog={blog} />
                        ))
                    ) : (
                        <p>No blog posts found!</p>
                    )
                }
            </Layout>
        );
    }

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

npm run dev

Это послужит вашей заявке на http://localhost:3000. Воспользуйтесь этой ссылкой и откройте приложение в браузере. В зависимости от добавленных сообщений ваша страница должна быть похожа на:

Получение отдельного поста

На этом этапе Remix может обслуживать сообщения в блоге. Однако мы не можем получить доступ к содержимому каждого отдельного сообщения. Для этого:

  • Создайте каталог posts внутри каталога app/routes.
  • Создайте файл $postId.jsx в каталоге posts.
  • В файл $postId.jsx импортируем необходимые модули:
import { useLoaderData } from '@remix-run/react';
    import { checkEnvVars, checkStatus } from '../../utils/errorHandling';
    import url from '../../utils/url';
    import { Layout } from '../../components';
    import styles from '../../components/style.css';
  • Настройте стили:
export const links = () => [
        { rel: "stylesheet", href: styles },
    ];
  • Настройте функцию загрузчика для получения каждого сообщения:
export async function loader({ params }) {
        const { postId } = params; // get the post id
        checkEnvVars(); // check the environmental variables
        const response = await fetch(`${process.env.STRAPI_URL_BASE}/api/blogs/${postId}?populate=hero`, {
            method: "GET",
            headers: {
                "Authorization": `Bearer ${process.env.STRAPI_API_TOKEN}`,
                "Content-Type": "application/json"
            }
        }); // send a request to strapi backend to get the post
    
        checkStatus(response); // check the response status
    
        const data = await response.json(); // get the json data
    
        if (data.error) {// check if we have an error
            throw new Response("Error loading data from strapi", { status: 500 });
        }
    
        return data.data; // return the data
    }
  • Настройте функцию рендеринга, чтобы получить данные и отобразить их:
export default function Post() {
        const blog = useLoaderData();
        const blogData = blog.attributes;
        return (
            <Layout>
                <div className="blog-post">
                    <div className="blog-post-hero">
                        <img src={`${url}${blogData.hero.data.attributes.url}`} alt={`${blogData.hero.data.attributes.alternativeText}`} />
                    </div>
                    <div className="blog-post-title">
                        <h1>{blogData.title}</h1>
                    </div>
                    <div className="blog-post-content">
                        <div dangerouslySetInnerHTML={{ __html: blogData.content }} />
                    </div>
                </div>
            </Layout>
        )
    }

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

Заключение

Strapi CMS используется для разработки и управления контентом любого приложения. Это помогает вам быстрее формировать любой API и использовать контент через Restful API и GraphQL. В этом руководстве мы создали Strapi Restful API, а затем использовали его для создания минималистического приложения для блога Remix.

Вы можете получить исходный код, используемый в этом проекте, в репозитории GitHub для части Remix Frontend.