Некоторое время назад я размышлял о своих интернет-привычках и, более конкретно, о том, что мне действительно нравится, когда я что-то читаю. Вот что я обычно делаю: Я делаю запрос, а затем просто позволяю себе руководствоваться наиболее интересными ссылками. Я всегда обнаруживаю, что читаю сообщения в блоге о чьем-то опыте, который совершенно не связан с запросом, который я первоначально набрал.
Блоггинг – это отличный способ поделиться опытом, убеждениями или отзывами. А Strapi поможет вам создать свой блог! Итак, я почти уверен, что теперь вы понимаете, о чем этот пост. Давайте узнаем, как создать блог с помощью вашей любимой техники – Strapi.
- Цель
- Предварительные условия
- Шаг 1: Настройка бэкенда
- Шаг 2: Настройка фронтенда
- Шаг 3: Запрос к Strapi с помощью GraphQL
- Шаг 4: Стилизация с помощью UIkit
- Шаг 5: Проектирование структуры данных
- Шаг 6: Создание макета приложения
- Шаг 7: Создайте компонент Статьи
- Шаг 8: Индексная страница
- Шаг 9: Создание страницы статьи
- Шаг 10: Категории
- Заключение
Цель
Если вы знакомы с нашим блогом, то наверняка видели, что мы выпустили серию туториалов о том, как создавать блоги с помощью Strapi с большим количеством frontend-фреймворков:
- React
- Next.js
- Vue.js
- Gatsby
Цель этой статьи – создать сайт блога, используя Strapi в качестве бэкенда, Nuxt для фронтенда и Apollo для запроса API Strapi с помощью GraphQL.
Нажмите здесь, чтобы получить доступ к исходному коду на GitHub.
Предварительные условия
Чтобы следовать этому руководству, вам потребуется установить последнюю версию Strapi и Nuxt на ваш компьютер, но не волнуйтесь, мы будем устанавливать их вместе!
Вам также потребуется установить Node.js v14 и это все.
Шаг 1: Настройка бэкенда
Начиная с версии beta.9, у нас есть замечательный пакет create strapi-app
, который позволяет создать проект Strapi за считанные секунды без необходимости глобальной установки Strapi, так что давайте попробуем его.
- Создайте папку blog-strapi и заходите внутрь!
mkdir blog-strapi
cd blog-strapi
- Создайте папку бэкенда Strapi, используя шаблон blog; скопируйте и вставьте в терминал следующую командную строку:
yarn create strapi-app backend --quickstart --no-run
Эта единственная командная строка создаст все необходимое для вашего бэкенда. Не забудьте добавить флаг --no-run
, поскольку он предотвратит автоматический запуск сервера вашим приложением.
SPOILER ALERT: сначала нам нужно установить несколько потрясающих плагинов Strapi.
Теперь, когда вы знаете, что нам нужно установить несколько плагинов для улучшения вашего приложения, давайте установим один из наших самых популярных – плагин GraphQL:
cd backend
yarn strapi install graphql
yarn develop
Откройте ваш Strapi dev-сервер по адресу http://localhost:1337.
После завершения установки вы можете запустить ваш Strapi dev-сервер и создать первого пользователя-администратора. Именно он будет иметь все права в вашем приложении, поэтому, пожалуйста, убедитесь, что вы ввели правильный пароль; (password123) действительно небезопасен.
Отлично! Теперь, когда Strapi готов, вы собираетесь создать свое приложение Nuxt.
Шаг 2: Настройка фронтенда
Ну что ж, самая простая часть завершена, давайте испачкаем руки, разрабатывая наш блог!
- Создайте проект Nuxt, выполнив следующую команду внутри
./blog-strapi
:
yarn create nuxt-app frontend
Примечание: Терминал запросит некоторые подробности о вашем проекте. Поскольку они не имеют отношения к нашему блогу, вы можете их проигнорировать. Однако я настоятельно советую вам прочитать документацию. Так что вперед, наслаждайтесь и жмите Enter до конца!
И снова, как только установка закончится, вы можете запустить свое внешнее приложение, чтобы убедиться, что все в порядке.
cd frontend
yarn dev
- Откройте ваш сервер Nuxt.js dev по адресу http://localhost:3000/.
Поскольку вы, возможно, хотите, чтобы люди читали ваш блог или сделать его “милым и красивым”, мы будем использовать популярный CSS фреймворк для стилизации: UIkit и Apollo GraphQL для запроса Strapi с помощью GraphQL.
Шаг 3: Запрос к Strapi с помощью GraphQL
Убедитесь, что вы находитесь в папке frontend
перед выполнением следующих команд.
- Установите все необходимые зависимости для Apollo, выполнив следующую команду:
// Ctrl + C to close Nuxt.js process
yarn add @nuxtjs/apollo
Apollo Client – это полнофункциональный кэширующий GraphQL-клиент с интеграциями для Vue, React и др. Он позволяет легко создавать компоненты пользовательского интерфейса, которые получают данные через GraphQL.
- Добавьте
@nuxtjs/apollo
в раздел modules с конфигурацией Apollo в./frontend/nuxt.config.js
.
// nuxt.config.js
export default {
modules: [
'@nuxtjs/apollo',
],
apollo: {
clientConfigs: {
default: {
httpEndpoint: process.env.BACKEND_URL || "http://localhost:1337/graphql",
}
}
},
}
Нам также понадобится использовать переменную env для нашего базового url Strapi, добавьте новую секцию env
в конце файла nuxt.config.js
:
// nuxt.config.js
export default {
env: {
strapiBaseUri: process.env.API_URL || "http://localhost:1337"
},
}
Отлично! Apollo теперь готов. 🚀
Шаг 4: Стилизация с помощью UIkit
UIkit – это легкий и модульный фронтенд-фреймворк для разработки быстрых и мощных веб-интерфейсов.
- Установите UIkit, выполнив следующую команду:
yarn add uikit
Теперь вам нужно инициализировать JS UIkit в вашем приложении Nuxt. Вы сделаете это, создав новый плагин.
- Создайте файл
./frontend/plugins/uikit.js
и скопируйте/вставьте следующий код:
import Vue from 'vue'
import UIkit from 'uikit/dist/js/uikit-core'
import Icons from 'uikit/dist/js/uikit-icons'
UIkit.use(Icons)
UIkit.container = '#__nuxt'
Vue.prototype.$uikit = UIkit
Add the following sections to your `nuxt.config.js` file:
// nuxt.config.js
export default {
css: [
'uikit/dist/css/uikit.min.css',
'@assets/css/main.css'
],
plugins: [
{ src: '~/plugins/uikit.js', ssr: false }
]
}
As you can see, you are including both UIkit and `main.css` files! We just need to create the `./frontend/assets/css/main.css` file.
a {
text-decoration: none;
}
h1 {
font-family: Staatliches;
font-size: 120px;
}
#category {
font-family: Staatliches;
font-weight: 500;
}
#title {
letter-spacing: .4px;
font-size: 22px;
font-size: 1.375rem;
line-height: 1.13636;
}
#banner {
margin: 20px;
height: 800px;
}
#editor {
font-size: 16px;
font-size: 1rem;
line-height: 1.75;
}
.uk-navbar-container {
background: #fff !important;
font-family: Staatliches;
}
img:hover {
opacity: 1;
transition: opacity 0.25s cubic-bezier(0.39, 0.575, 0.565, 1);
}
**Note:** You don't need to understand what's in this file. It's just some styling ;)
Let's add a beautiful font [Staatliches](https://fonts.google.com/specimen/Staatliches) to the project! Add the following code to your `link` section in your `nuxt.config.js`
// nuxt.config.js
export default {
link: [
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Staatliches' }
],
}
Отлично! Запустите yarn dev
для перезапуска вашего сервера и будьте готовы получить впечатление от первой страницы вашего приложения!
Великолепно! Пришло время немного структурировать наш код.
Шаг 5: Проектирование структуры данных
Наконец, мы собираемся создать структуру данных наших статей, создав тип содержимого Article.
- Зайдите в админ-панель Strapi и нажмите на “Content-Type Builder”.
- Нажмите на “Создать новый тип коллекции”.
Теперь вам будет предложено создать все поля для вашего типа содержимого
-
Создайте следующие поля:
-
Field Text “title”
-
ПолеRich Text “содержание”
-
Поле Media “изображение”, одно изображение
Нажмите Сохранить! Вот и все, ваш тип содержимого “Статья” создан.
Возможно, вы захотите создать свою первую статью, но перед этим нам нужно сделать одну вещь: Предоставьте доступ к типу контента “Статья”.
- Нажмите на Настройки, затем Роли и выберите роль “Публичный”.
Отлично! Вы должны быть готовы создать свою первую статью прямо сейчас и получить ее на GraphQL Playground.
Итак, создайте свою первую статью! Вот пример:
Отлично! Теперь вы, возможно, захотите достичь того момента, когда вы действительно сможете получить свои статьи через API! Перейдите на сайт http://localhost:1337/api/articles Разве это не круто!
Вы также можете поиграть с GraphQL Playground.
Возможно, вы захотите назначить категорию для своих статей (новости, тренды, мнения). Вы сделаете это, создав еще один тип контента в Strapi.
Создайте тип контента “Категория” со следующим полем
- Текст поля “название”
Нажмите сохранить!
Создайте новое поле в типе контента “Статья”, которое является отношением Категория имеет много статей
, как показано ниже:
Снова откройте Settings, затем Roles и нажмите на роль “Public”, затем отметьте маршруты категорий find
и findone
и сохраните.
Теперь вы сможете выбрать категорию для вашей статьи в правом боковом блоке.
Теперь, когда мы хорошо разобрались со Strapi, давайте поработаем над фронтендом!
Шаг 6: Создание макета приложения
Вы можете изменить стандартный макет приложения Nuxt.js, создав свой собственный файл layouts/default.vue
.
<template>
<div>
<nav class="uk-navbar-container" uk-navbar>
<div class="uk-navbar-left">
<ul class="uk-navbar-nav">
<li>
<a href="#modal-full" uk-toggle
><span uk-icon="icon: table"></span
></a>
</li>
<li>
<a href="/">Strapi Blog </a>
</li>
</ul>
</div>
<div class="uk-navbar-right">
<ul class="uk-navbar-nav">
<li v-for="category in categories.data" :key="category.id">
<NuxtLink
:to="{ name: 'categories-id', params: { id: category.id } }"
>{{ category.attributes.name }}
</NuxtLink>
</li>
</ul>
</div>
</nav>
<div id="modal-full" class="uk-modal-full" uk-modal>
<div class="uk-modal-dialog">
<button
class="uk-modal-close-full uk-close-large"
type="button"
uk-close
></button>
<div
class="uk-grid-collapse uk-child-width-1-2@s uk-flex-middle"
uk-grid
>
<div
class="uk-background-cover"
style="
background-image: url('https://images.unsplash.com/photo-1493612276216-ee3925520721?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3308&q=80 3308w');
"
uk-height-viewport
></div>
<div class="uk-padding-large">
<h1 style="font-family: Staatliches">Strapi blog</h1>
<div class="uk-width-1-2@s">
<ul class="uk-nav-primary uk-nav-parent-icon" uk-nav>
<li v-for="category in categories.data" :key="category.id">
<NuxtLink
class="uk-modal-close"
:to="{ name: 'categories-id', params: { id: category.id } }"
>{{ category.attributes.name }}
</NuxtLink>
</li>
</ul>
</div>
<p class="uk-text-light">Built with strapi</p>
</div>
</div>
</div>
</div>
<Nuxt />
</div>
</template>
<script>
export default {
data() {
return {
categories: {
data: [],
},
};
},
};
</script>
Как вы можете видеть, список categories
пуст. На самом деле, вы хотите иметь возможность выводить список всех категорий в вашей навигационной панели. Для этого нам нужно получить их с помощью Apollo, давайте напишем запрос!
- Создайте папку
apollo/queries/category
и внутри нее файлcategories.gql
со следующим кодом:
query {
categories {
data {
id
attributes {
name
}
}
}
}
- Замените тег
script
в файлеdefault.vue
следующим кодом:
<script>
import categoriesQuery from "~/apollo/queries/category/categories";
export default {
data() {
return {
categories: {
data: [],
},
};
},
apollo: {
categories: {
prefetch: true,
query: categoriesQuery,
},
},
};
</script>
Примечание: Текущий код не подходит для отображения большого количества категорий, так как вы можете столкнуться с проблемой пользовательского интерфейса.
Поскольку эта статья в блоге должна быть короткой, я позволю вам улучшить код, возможно, добавить ленивую загрузку или что-то еще. Пока что ссылки не работают, вы поработаете над этим позже в учебнике 🙂
Шаг 7: Создайте компонент Статьи
Этот компонент будет отображать все ваши статьи на разных страницах, так что перечисление их через компонент – неплохая идея.
- Создайте файл
components/Articles.vue
, содержащий следующее:
<template>
<div>
<div class="uk-child-width-1-2" uk-grid>
<div>
<router-link
v-for="article in leftArticles"
:to="{ name: 'articles-id', params: { id: article.id } }"
class="uk-link-reset"
:key="article.id"
>
<div class="uk-card uk-card-muted">
<div v-if="article.attributes.image.data" class="uk-card-media-top">
<img
:src="api_url + article.attributes.image.data.attributes.url"
alt=""
height="100"
/>
</div>
<div class="uk-card-body">
<p
id="category"
v-if="article.attributes.category.data"
class="uk-text-uppercase"
>
{{ article.attributes.category.data.attributes.name }}
</p>
<p id="title" class="uk-text-large">
{{ article.attributes.title }}
</p>
</div>
</div>
</router-link>
</div>
<div>
<div class="uk-child-width-1-2@m uk-grid-match" uk-grid>
<router-link
v-for="article in rightArticles"
:to="{ name: 'articles-id', params: { id: article.id } }"
class="uk-link-reset"
:key="article.id"
>
<div class="uk-card uk-card-muted">
<div
v-if="article.attributes.image.data"
class="uk-card-media-top"
>
<img
:src="api_url + article.attributes.image.data.attributes.url"
alt=""
height="100"
/>
</div>
<div class="uk-card-body">
<p
id="category"
v-if="article.attributes.category.data"
class="uk-text-uppercase"
>
{{ article.attributes.category.data.attributes.name }}
</p>
<p id="title" class="uk-text-large">
{{ article.attributes.title }}
</p>
</div>
</div>
</router-link>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
api_url: process.env.strapiBaseUri,
};
},
props: {
articles: Object,
},
computed: {
leftArticlesCount() {
return Math.ceil(this.articles.data.length / 5);
},
leftArticles() {
return this.articles.data.slice(0, this.leftArticlesCount);
},
rightArticles() {
return this.articles.data.slice(
this.leftArticlesCount,
this.articles.length
);
},
},
};
</script>
Как вы видите, вы получаете статьи благодаря GraphQl-запросу, давайте напишем его!
- Создайте новый файл
apollo/queries/article/articles.gql
, содержащий следующее:
query {
articles {
data {
id
attributes {
title
content
image {
data {
attributes {
url
}
}
}
category {
data {
attributes {
name
}
}
}
}
}
}
}
Потрясающе! Теперь вы можете создать свою главную страницу.
Шаг 8: Индексная страница
Вы хотите перечислить все статьи на вашей индексной странице, давайте воспользуемся нашим новым компонентом! Обновите код в файле pages/index.vue
:
<template>
<div>
<div class="uk-section">
<div class="uk-container uk-container-large">
<h1>Strapi blog</h1>
<Articles :articles="articles"></Articles>
</div>
</div>
</div>
</template>
<script>
import articlesQuery from "~/apollo/queries/article/articles";
import Articles from "~/components/Articles";
export default {
data() {
return {
articles: {
data: [],
},
};
},
components: {
Articles,
},
apollo: {
articles: {
prefetch: true,
query: articlesQuery,
},
},
};
</script>
Отлично! Теперь вы достигли момента, когда вы действительно можете получать статьи через GraphQL API!
Вы можете видеть, что при нажатии на статью ничего нет. Давайте вместе создадим страницу статьи!
Шаг 9: Создание страницы статьи
- Создайте папку
pages/articles
и внутри нее новый файл_id.vue
, содержащий следующее:
<template>
<div>
<div
v-if="article.data.attributes.image.data"
id="banner"
class="uk-height-small uk-flex uk-flex-center uk-flex-middle uk-background-cover uk-light uk-padding"
:data-src="api_url + article.data.attributes.image.data.attributes.url"
uk-img
>
<h1>{{ article.data.attributes.title }}</h1>
</div>
<div class="uk-section">
<div class="uk-container uk-container-small">
<div v-if="article.data.attributes.content" id="editor">
{{ article.data.attributes.content }}
</div>
<p v-if="article.data.publishedAt">
{{ article.data.attributes.publishedAt }}
</p>
</div>
</div>
</div>
</template>
<script>
import articleQuery from "~/apollo/queries/article/article";
export default {
data() {
return {
article: {
data: [],
},
api_url: process.env.strapiBaseUri,
};
},
apollo: {
article: {
prefetch: true,
query: articleQuery,
variables() {
return { id: parseInt(this.$route.params.id) };
},
},
},
};
</script>
Здесь вы получаете только одну статью, давайте напишем запрос для нее! Создайте файл apollo/queries/article/article.gql
, содержащий следующее:
query Articles($id: ID!) {
article(id: $id) {
data {
id
attributes {
title
content
image {
data {
attributes {
url
}
}
}
publishedAt
}
}
}
}
Итак, вы можете захотеть отобразить ваш контент в формате Markdown
- Установите
markdownit
с помощьюyarn add @nuxtjs/markdownit
. - Установите
date-fns
с помощьюyarn add @nuxtjs/date-fns
. - Добавьте его в ваши модули внутри вашего файла
nuxt.config.js
и добавьте конфигурацию объекта markdownit прямо под// nuxt.config.js
.
export default {
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
'@nuxtjs/date-fns',
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
'@nuxtjs/apollo',
'@nuxtjs/markdownit'
],
// [optional] markdownit options
// See https://github.com/markdown-it/markdown-it
markdownit: {
preset: 'default',
linkify: true,
breaks: true,
injected: true
}
}
-
Используйте его для отображения содержимого внутри вашего файла
_id.vue
, заменив строку, отвечающую за отображение содержимого.// pages/articles/_id.vue
Шаг 10: Категории
Давайте теперь создадим страницу для каждой категории! Создайте папку pages/categories
и внутри нее файл _id.vue
, содержащий следующее:
<template>
<div>
<client-only>
<div class="uk-section">
<div class="uk-container uk-container-large">
<h1>{{ category.data.attributes.name }}</h1>
<Articles :articles="category.data.attributes.articles"></Articles>
</div>
</div>
</client-only>
</div>
</template>
<script>
import articlesQuery from "~/apollo/queries/article/articles-categories";
import Articles from "~/components/Articles";
export default {
data() {
return {
category: {
data: [],
},
};
},
components: {
Articles,
},
apollo: {
category: {
prefetch: true,
query: articlesQuery,
variables() {
return { id: parseInt(this.$route.params.id) };
},
},
},
};
</script>
И не забудьте про запрос! Создайте apollo/queries/article/articles-categories.gql
, содержащий следующее:
query Category($id: ID!){
category(id: $id) {
data {
attributes {
name
articles {
id
data {
attributes {
title
content
image {
data {
attributes {
url
}
}
}
category {
data {
attributes {
name
}
}
}
}
}
}
}
}
}
}
Потрясающе! Теперь вы можете перемещаться по категориям 🙂
Заключение
Огромные поздравления, вы успешно справились с этим уроком. Надеюсь, вам понравилось!
Нажмите здесь, чтобы получить доступ к исходному коду на GitHub.
Все еще голодны?
Не стесняйтесь добавлять дополнительные функции, адаптировать этот проект под свои нужды и оставлять свои отзывы в разделе комментариев.
Если вы хотите развернуть свое приложение, ознакомьтесь с документацией.