Автор: Сумит Харче

Эта статья была обновлена ​​до версии 4 автором Mark Munyaka.

Узнайте, как создать простое, но невероятно быстрое приложение для блога с помощью Blazor WebAssembly, Tailwind CSS и Strapi. Вы будете использовать Strapi, ведущую безголовую CMS с открытым исходным кодом, для хранения ваших сообщений и Blazor для создания внешнего интерфейса.

Предпосылки

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

  1. Страпи — начнем здесь.
  2. Node.js
  3. Блейзор
  4. C#
  5. Шелл (Баш)

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

  • .NET SDK. Версия 6 на момент написания
  • Узел v14.x.x или v16.x.x. Узел загрузки из раздела Загрузить | Страница Node.js. Я использовал Node v16.14.2.
  • npm или yarn. npm поставляется с вашей установкой Node. Если вы предпочитаете пряжу, установите ее как пакет npm. Отметьте Установка | Пряжа.

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

Введение

Что такое Блазор?

Blazor — это веб-фреймворк от Microsoft, который позволяет создавать веб-приложения с использованием C# и HTML. Если вы разработчик, использующий C#, и хотите создать молниеносно быстрое веб-приложение, вам следует проверить Blazor.

Согласно документам Blazor:

Blazor — это бесплатная веб-инфраструктура с открытым исходным кодом, которая позволяет разработчикам создавать веб-приложения с использованием C# и HTML.

Blazor позволяет создавать интерактивные веб-интерфейсы с помощью C# вместо JavaScript. Приложения Blazor состоят из многократно используемых компонентов веб-интерфейса, реализованных с помощью C#, HTML и CSS.

И клиентский, и серверный код написаны на C#, что позволяет вам совместно использовать код и библиотеки. Blazor может запускать код C# на стороне клиента непосредственно в браузере с помощью WebAssembly. Поскольку это настоящая .NET, работающая на WebAssembly, вы можете повторно использовать код и библиотеки из серверных частей вашего приложения.

В этой статье вы будете использовать Blazor Web Assembly для создания клиентской части приложения блога.

Что такое Страпи?

Strapi — это ведущая безголовая CMS с открытым исходным кодом, основанная на Node.js для разработки и управления контентом с использованием Restful API и GraphQL.

С помощью Strapi мы можем быстрее формировать наш API и использовать контент через API, используя любой клиент HTTP RESTful или внешний интерфейс с поддержкой GraphQL.

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

Шаг 1: Создание проекта Strapi

Откройте свой терминал и создайте пустой каталог проекта для хранения вашего проекта. Эта папка будет служить корневой папкой. Внешний и внутренний код будут храниться в подкаталогах. Я назову каталог своего проекта Purplerhino.

$ mkdir purplerhino

Измените каталог на каталог проекта Purplerhino.

$ cd purplerhino

Включите систему управления версиями для вашего проекта, инициализировав репозиторий git.

/purplerhino $ git init

Создайте приложение Strapi.

/purplerhino $ npx create-strapi-app backend --quickstart

Приведенная выше команда создаст новый проект Strapi в каталоге с именем backend. Флаг quickstart настраивает ваше приложение Strapi с базой данных SQLite.

После успешной установки приложение Strapi запускается автоматически. Откройте интерфейс Регистрация администратора Strapi в веб-браузере по адресу localhost:1337/admin. Создайте пользователя-администратора для своего приложения Strapi и нажмите Начать.

Шаг 2. Создайте коллекцию сообщений

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

Мы создадим тип контента с именем posts, содержащий следующие поля: title, content, author и image.

  • Нажмите Конструктор типов контента в левой части страницы.
  • Выберите + Создать новый тип подборки в левой части страницы и введите Post в качестве отображаемого имени.
  • Нажмите Продолжить, чтобы создать новую коллекцию Post.

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

Мы будем использовать пользовательский интерфейс администратора для создания сообщения.

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

  • Выберите Text и введите title в текстовом поле.
  • Нажмите на + Add another field, выберите Rich Text и назовите его content.
  • Нажмите на + Add another field и выберите поле Media и назовите его image.
  • Выберите + Add another field еще раз, выберите поле Text и назовите его author.
  • После добавления всех необходимых полей нажмите ✓ Сохранить, чтобы сохранить коллекцию и дождаться перезапуска сервера Strapi.

  • Нажмите Диспетчер контента в левой части панели инструментов. В разделе ТИПЫ СБОРНИКОВ выберите Опубликовать.
  • Затем нажмите + Создать новую запись и добавьте несколько сообщений в свою коллекцию Сообщения. Нажмите Сохранить и ✓ Опубликовать для каждого добавляемого сообщения.

Шаг 3. Сделайте Strapi API общедоступным

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

  • Нажмите Настройки на боковой панели.
  • В разделе ПЛАГИН ПОЛЬЗОВАТЕЛЕЙ И РАЗРЕШЕНИЙ нажмите Роли.
  • На странице Роли нажмите Общедоступно.

  • Прокрутите вниз до раздела Разрешения:
  • Выберите Опубликовать и установите флажок Выбрать все. Это делает все конечные точки общедоступными по адресу localhost:1337/api/post.
  • Нажмите ✓ Сохранить.

Шаг 4: Установите и включите плагин Transformer

Нам нужно будет преобразовать JSON из запроса API для работы с нашим интерфейсом Blazor. Для этого воспользуемся Трансформером от @ComfortablyCoding.

  • Остановите сервер Strapi, нажав Ctrl + C на клавиатуре.
  • Установите Transformer в корневую папку вашего приложения Strapi.
/purplerhino/backend $ npm install strapi-plugin-transformer
  • Создайте файл plugins.js в папке config для настройки вашего плагина.
/purplerhino/backend $ touch config/plugins.js
  • Добавьте эту конфигурацию в ./config/plugins.js.
module.exports = ({ env }) => ({
 'transformer': {
    enabled: true,
    config: {
      prefix: '/api/',
      responseTransforms: {
        removeAttributesKey: true,
        removeDataKey: true,
      }
    }
  },
});

Эта конфигурация предоставит ответ API, который будет работать с настройкой вашего внешнего приложения Blazor.

  • Перестройте приложение Strapi и запустите сервер, чтобы изменения вступили в силу.
/purplerhino/backend $ yarn build
/purplerhino/backend $ yarn develop

Настройка внешнего интерфейса

Шаг 5: Настройка проекта Blazor

Давайте настроим наше внешнее приложение Blazor, используя интерфейс командной строки (CLI) .NET для выполнения команд.

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

/purplerhino $ dotnet new blazorwasm -o frontend
/purplerhino $ cd frontend
/purplerhino/frontend $ dotnet run

Откройте localhost: 5024 в браузере, чтобы увидеть приложение Blazor frontend.

Шаг 6. Интегрируйте API Strapi с приложением Blazor

Теперь ваш проект Blazor установлен; Следующим шагом является создание внешнего интерфейса блога.

Чтобы получить доступ к сообщениям, вам нужно будет использовать URL-адрес API Strapi, который имеет вид localhost:1337/api.

В папке frontend/wwwroot создайте файл с именем appsettings.json для хранения URL-адреса API Strapi.

/purplerhino/frontend $ touch wwwroot/appsettings.json

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

{
    "AppSettings": {
    "STRAPI_API_URL": "https://localhost:1337" 
    }
}

Создайте папку с именем Models и создайте в ней файл с именем AppSettings.cs.

/purplerhino/frontend $ mkdir Models
/purplerhino/frontend $ touch Models/AppSettings.cs

Добавьте следующий код в Models/AppSettings.cs:

// ./Models/AppSettings.cs

namespace frontend.Models
{
    public class AppSettings
    {
        public string STRAPI_API_URL { get; set; }
    }
}

Теперь откройте файл Program.cs и приведенный ниже код. Это необходимо для чтения данных из файла appsettings.json из любой точки приложения.

// ./Program.cs

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using frontend.Models;
using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace frontend
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");

            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

            await builder.Build().RunAsync();
        }

        public static void ConfigureServices(IServiceCollection services)
        {
            // Example of loading a configuration as configuration isn't available yet at this stage.
            services.AddSingleton(provider =>
            {
                var config = provider.GetService<IConfiguration>();
                return config.GetSection("App").Get<AppSettings>();
            });
        }
    }
}

Вы только что настроили интеграцию API Strapi с приложением Blazor. Следующим шагом будет создание компонента для вашего блог-приложения.

Шаг 7. Отобразите все записи блога на главной странице.

Мы используем Tailwind CSS для оформления нашего замечательного блога. Итак, откройте файл index.html в папке wwwroot и добавьте этот фрагмент HTML в раздел <head></head>.

<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">

Теперь откройте файл Pages/Index.razor и замените существующий код кодом ниже, чтобы отобразить все сообщения, полученные из Strapi, в ваше клиентское приложение:

@* ./Pages/Index.razor *@

@page "/"
@inject HttpClient Http
@using Microsoft.Extensions.Configuration;
@using Models
@inject IConfiguration Configuration

@if (allPosts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <section class="text-gray-600 body-font">
    <div class="container px-5 py-4 mx-auto">
        <div class="text-center mb-20">
            <h1 class="sm:text-3xl text-2xl font-medium title-font text-gray-900 mb-4">Strapi Blazor Blog App</h1>
            <p class="text-base leading-relaxed xl:w-2/4 lg:w-3/4 mx-auto text-gray-500s">British History - From the Anglo-Saxon era to present day Britain.</p>
            <div class="flex mt-6 justify-center">
                <div class="w-16 h-1 rounded-full bg-indigo-500 inline-flex"></div>
            </div>
        </div>
        <div class="flex flex-wrap -m-3">
            @foreach (var post in allPosts.data)
                {
                    <div class="xl:w-1/4 md:w-1/2 p-4">
                        <div class="bg-gray-100 p-6 rounded-lg">
                            <img class="h-40 rounded w-full object-cover object-center mb-6" src="@post.Image.Url"
                        alt="content">
                            <h2 class="text-lg text-gray-900 font-medium title-font mb-4">@post.Title</h2>
                            <NavLink href="@($"post/{post.Id.ToString()}")">
                                <a class="text-indigo-500 inline-flex items-center">
                                    Read More
                                    <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
                                stroke-width="2" class="w-4 h-4 ml-2" viewBox="0 0 24 24">
                                        <path d="M5 12h14M12 5l7 7-7 7"></path>
                                    </svg>
                                </a>
                            </NavLink>
                        </div>
                    </div>
                }
            </div>
        </div>
    </section>
}


@code {
    private PostList allPosts = null;
    public string strapi_api_url;

    protected override async Task OnInitializedAsync()
    {
        strapi_api_url = Configuration["AppSettings:STRAPI_API_URL"];
        var url = "{STRAPI_API_URL}/api/posts?populate=*";
        allPosts = await Http.GetFromJsonAsync<PostList>(url.Replace("{STRAPI_API_URL}", strapi_api_url));
        if (allPosts.data != null)
        {
            foreach (var post in allPosts.data)
            {
                post.Image.Url = strapi_api_url + post.Image.Url;
            }
        }
    }

    public class Post
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public string Author { get; set; }
        public Image Image { get; set; }
    }

    public class Image
    {
        public string Url { get; set; }
    }

    public class PostList
    {
        public List<Post> data { get; set; }
    }

}

Вот краткое объяснение того, что делает код:

  • Верхний раздел от @pageдо @inject представляет собой список всех библиотек, которые Index.razor необходимо использовать для получения данных из API Strapi.
  • Следующий раздел с @if (allPosts == null) по </section>} — это HTML-код, необходимый для отображения сообщений из API Strapi. @foreach будет перебирать все сообщения, извлекать image, title и id каждого сообщения и отображать каждое сообщение на своей карточке.
  • Раздел @code представляет собой код C#. Post, Image и PostList — это классы, которые мы будем использовать для сопоставления данных JSON из ответа API. allPosts является экземпляром PostList. Данные JSON из url будут преобразованы в allPosts с помощью функции Http.GetFromJsonAsync(). Цикл @foreach будет получать URL-адреса изображений каждого сообщения.

Обновите файл Shared/NavMenu.razor, чтобы удалить дополнительное меню с боковой панели. Замените существующий код следующим кодом:

@* ./Shared/NavMenu.razor *@

<header class="text-gray-600 body-font">
    <div class="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center">
        <a class="flex order-first lg:order-none lg:w-1/5 title-font font-medium items-center text-gray-900 lg:items-center lg:justify-center mb-4 md:mb-0">
            <img src="/blazor_strapi_logo.png" alt="logo" style="height:60px" />
            <span class="ml-3 text-3xl">StrapiBlazorBlog</span>
        </a>
    </div>
</header>

Обновите файл Shared/MainLayout.razor, как показано ниже:

@* ./Shared/MainLayout.razor *@

@inherits LayoutComponentBase

<div>
<NavMenu />

<div>
    @Body
</div>
</div>

Теперь запустите приложение и перейдите к localhost: 5024 в вашем браузере.

Вау 👌 Мы успешно отобразили все наши посты на главной странице.

Шаг 8. Отобразите один пост в блоге.

Нам удалось отобразить все сообщения на одной странице, но у каждого сообщения нет своей страницы, и кнопка Подробнее на главной странице тоже не работает. Давайте исправим это.

Создайте файл с именем PostDetails.razor в папке Pages.

/purplerhino/frontend $ touch Pages/PostDetails.razor

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

@* ./Pages/PostDetails.razor *@

@page "/post/{Id}"
@inject HttpClient Http
@inject NavigationManager NavigationManager
@using System.Text.Json.Serialization
@using Microsoft.Extensions.Configuration;
@using Models
@inject IConfiguration Configuration

@if (postDetails == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <section class="text-gray-700 body-font">
        <div class="container mx-auto flex px-5 pb-24 items-center justify-center flex-col">
            <h1 class="title-font sm:text-4xl text-3xl mb-4 font-medium text-gray-900">@postDetails.Data.Title</h1>
            <img class=" mb-10 object-cover object-center rounded" alt="hero" src="@postDetails.Data.Image.Url" style="height:400px;width:900px">
            <div class=" w-full">
                <div class="mb-8 leading-relaxed">@((MarkupString)postDetails.Data.Content)</div>
            </div>
            <div class="p-2 w-full">
                <button class="flex mx-auto text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg" @onclick="NavigateToIndexComponent">Back</button>
            </div>
        </div>
    </section>
}

@code {
    [Parameter] public string Id { get; set; }

    private PostSingle postDetails = null;

    public string strapi_api_url;

    protected override async Task OnInitializedAsync()
    {

        strapi_api_url = Configuration["AppSettings:STRAPI_API_URL"];
        var url = "{STRAPI_API_URL}/api/posts/{Id}?populate=*";
        url = url.Replace("{STRAPI_API_URL}", strapi_api_url);
        url = url.Replace("{Id}", Id);
        postDetails = await Http.GetFromJsonAsync<PostSingle>(url);

        if (postDetails.Data != null)
        {
            postDetails.Data.Image.Url = strapi_api_url + postDetails.Data.Image.Url;
        }
    }

    private void NavigateToIndexComponent()
    {
        NavigationManager.NavigateTo("");
    }

    public class PostSingle
    {
        public Data Data { get; set; }
    }
     public class Data
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public string Author { get; set; }
        public Image Image { get; set; }
    }

    public class Image
    {
        public string Url { get; set; }
    }

}

Вот краткое объяснение того, что делает код.

  • @page "/post/{Id}" относится к URL-адресу страницы, которая будет отображаться на основе идентификатора сообщения.
  • От @if (postDetaills == null) до </section> — это разметка для отображения страницы, в которой используются title, image и content сообщения, полученные из API Strapi.
  • Раздел @code содержит классы для заполнения данными из API Strapi, как и в Index.razor, за исключением того, что запрос API относится к одному посту, а не ко всем.

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

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

Шаг 9. Разверните приложение блога

Серверный API Strapi и наше внешнее приложение Blazor работают, и следующим шагом будет развертывание вашего приложения. Среди доступных вариантов вы можете развернуть Strapi API на Heroku. Чтобы развернуть приложение Blazor WebAssembly на Netlify, ознакомьтесь с разделом Как развернуть приложение Blazor на Netlify.

Заключение

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

Вы можете скачать исходный код реализации с Github. Дайте мне знать, если у вас есть какие-либо комментарии, вопросы или предложения. Команда Strapi всегда готова помочь вам.