Вы собираетесь создать блог? А может быть, вы хотите начать использовать волшебный Flotiq с NextJS? Если вы ответили «да» на любой вопрос, продолжайте читать наш учебник. Вы узнаете, как шаг за шагом создать новый проект.
Привет! Сегодня мы хотим показать, как создать простой блог с помощью нашего шаблона NextJS. Мы рассмотрим основные шаги и приведем примеры кода. Наконец, мы поделимся результатом в виде готового к использованию NextJS blog starter.
1. Что такое NextJS?
React — это библиотека для создания пользовательских интерфейсов. NextJS — это фреймворк, предназначенный для облегчения создания таких интерфейсов. Например, этот инструмент предоставляет систему маршрутизации на основе файлов и поддержку CSS.
2. Какие технологии будут полезны?
Конечно, мы хотим использовать Flotiq в качестве базы и места для управления контентом. В этом учебнике мы хотим создать фронтенд (визуальную) часть.
У вас должны быть базовые знания:
- React
- Webpack
- Tailwind .
Но давайте покажем кое-что в деталях
3. Определение контента Flotiq
В этой статье мы полагаемся на предопределенное определение типа контента Blog post Content Type Definition. Вы можете создать его просто из приборной панели Flotiq:
На этом этапе вы также можете добавить примеры постов в только что созданный тип содержимого Blog Post.
Примечание: Для создания определений типов содержимого с данными примера в вашем аккаунте вы также можете использовать подход Flotiq CLI. Загрузите данные из каталога .flotiq в стартовом репозитории и используйте команду flotiq import.
4. Какие компоненты нам нужно создать?
Наш блог будет состоять из небольших элементов, которые мы сможем использовать повторно в дальнейшем. Список компонентов нашего блога:
- Заголовок
- Нижний колонтитул
- CardAnnouncement
- Автор записи блога
- Blog Post FeaturedImage
- Теги записи блога
- Заметка в блоге Метаданные
- Заметка в блоге МетаданныеПрезентация
- Заметка в блоге Навигация
Но компоненты — это еще не все. Мы должны использовать некоторые макеты. Об этом — в следующем параграфе.
5. Давайте соединим наши компоненты с макетами/шаблонами
В нашем примере мы хотим создать две вещи: Макет записи блога и базовый шаблон. Начнем с базового шаблона, потому что от него будут зависеть все наши страницы.
import React from 'react';
import Head from 'next/head';
import Header from '../components/Header';
import Footer from '../components/Footer';
const Layout = ({ children, additionalClass = [], title, description }) => (
<main className={['font-sora', 'px-4', ...additionalClass].join(' ')}>
<Head>
<title>{title}</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<meta property="og:title" content={title} key="title" />
<meta name="description" content={description} />
</Head>
<Header />
{children}
<Footer />
</main>
);
export default Layout;
Это простой файл, содержащий наш Header, footer и HTML-тег Head для отображения заголовка в браузере. Важным моментом здесь является {children} — там, где мы поместим этот элемент, будут отображаться все дочерние компоненты (наши компоненты, содержимое страниц).
Во-вторых, как уже говорилось, у нас должен быть макет записи блога. Для его создания у нас должны быть некоторые компоненты, определенные ранее в нашей статье, и некоторые из пакета flotiq-components-react: Header, Content, BlogPostFeaturedImage, BlogPostAuthor, BlogPostMetaDetails и BlogPostNavigation. Конечно, мы не можем забыть о макете, определенном в этом разделе.
import React from 'react';
import moment from 'moment';
import { Content, Header } from 'flotiq-components-react';
import Layout from '../layouts/layout';
import BlogPostFeaturedImage from '../components/blog-post/BlogPostFeaturedImage';
import BlogPostAuthor from '../components/blog-post/BlogPostAuthor';
import BlogPostMetaDetails from '../components/blog-post/BlogPostMetaDetails';
import BlogPostNavigation from '../components/blog-post/BlogPostNavigation';
import config from '../lib/config';
const BlogPostTemplate = ({ post, pageContext }) => (
<Layout
title={`${config.siteMetadata.title} | ${post.title}`}
description={post.excerpt}
additionalClass={['bg-white px-6']}
>
<article className="max-w-7xl mx-auto mt-20 pb-4 rounded-2xl bg-light-gray overflow-hidden">
{(post.headerImage && post.headerImage[0].dataUrl) && (
<BlogPostFeaturedImage headerImage={post.headerImage} title={post.title} />
)}
<BlogPostMetaDetails
date={moment(post.internal.createdAt).format(' Do MMMM yyyy')}
readingTime=" 7 min"
tags={['#photo', '#cookig', '#food']}
additionalClass={['py-6']}
/>
<Header alignement="center" additionalClasses={['px-4 md:px-12 pt-10 pb-10']}>
{post.title}
</Header>
<Content
blocks={post.content.blocks}
additionalClasses={['px-4 md:px-12 text-sm md:text-lg']}
fileProps={{
audioProps: { additionalClasses: ['px-6 md:px-12 w-full md:w-3/5 mx-auto'] },
imageProps: {
additionalClasses: ['w-full md:w-9/12 m-auto'],
rounded: '3xl',
captionAdditionalClasses: ['w-full md:w-9/12 m-auto'],
},
}}
quoteProps={
{
variant: 'dark',
additionalClasses: ['px-12 md:px-28 py-4'],
captionAdditionalClasses: ['bg-primary rounded px-8 py-1.5 opacity-100'],
}
}
paragraphProps={{ additionalClasses: ['font-light'] }}
/>
<BlogPostAuthor authorName=" John Doe" additionalClass={['py-5']} />
</article>
<BlogPostNavigation
additionalClass={['mt-3']}
prevText="Previous post"
nextText="Next post"
pageContext={pageContext}
/>
</Layout>
);
export default BlogPostTemplate;
Теперь мы подготовились к созданию страниц 🙂
6. Маршрутизация — создание страниц
Прежде всего, стоит поближе познакомиться с системой маршрутизации в NextJS — она зависит от файлов. В директории pages мы можем создать, например, 404.js, но мы можем создать файл с именем [page].js — это страница, которая получает параметр page из URL.
Мы должны зависеть от двух функций: getStaticProps и getStaticPaths. Во второй мы можем сохранить нашу логику для генерации страниц в данном примере в зависимости от пагинации. В первой мы должны подготовить данные для каждой страницы. Конечно, в том же файле мы должны определить компоненты для рендеринга наших данных.
import Pagination from 'flotiq-components-react/dist/components/Pagination/Pagination';
import React from 'react';import Layout from '../layouts/layout';
import Announcement from '../components/Announcement';
import { getBlogPosts } from '../lib/blogPosts';
import BlogCards from '../sections/BlogCards';
import config from '../lib/config';
const Home = ({ posts, pageContext }) => (
<Layout
title={config.siteMetadata.title}
description={config.siteMetadata.description}
additionalClass={['bg-light-gray']}
>
<Announcement
content="This is the Blog where you can find any kind of information and rich media content.
Use it for your needs, add content and customize in any way"
/>
<BlogCards posts={posts} />
{pageContext.numPages > 1 && (
<Pagination page={pageContext.currentPage} numOfPages={pageContext.numPages} rounded="md" />
)}
</Layout>);
export async function getStaticProps({ params }) {
const fetchPost = await getBlogPosts(params.page, config.blog.postPerPage);
return {
props: {
posts: fetchPost.data,
pageContext: {
currentPage: params.page,
numPages: fetchPost.total_pages,
},
},
};
}
export async function getStaticPaths() {
const fetcher = await getBlogPosts(1, config.blog.postPerPage);
const pages = fetcher.total_pages;
const pathRule = (number) => `${number + 1}`;
let paths = {};
if (pages > 1) {
paths = Array.from(Array(pages - 1).keys()).map((i) => ({
params: { page: pathRule(i) },
}));
} else {
paths = Array.from(Array(pages).keys()).map((i) => ({
params: { page: pathRule(i) },
}));
}
return {
paths,
fallback: false,
};
}
export default Home;
Мы не можем создать несколько страниц, требующих подобной генерации на одном уровне. Мы должны создать новый каталог для наших постов. Давайте создадим страницу для генерации наших постов по slug. Конечно, мы должны назвать наш файл как [slug].js
import React from "react";
import BlogPostTemplate from "../../templates/blog-post";
import {
getBlogPostBySlug,
getBlogPosts,
getNextBlogPost,
getPreviousBlogPost,
} from "../../lib/blogPosts";
const Home = ({ post, pageContext }) => (
<BlogPostTemplate
post={post}
pageContext={{
pageContext,
}}
/>
);
export async function getStaticProps({ params }) {
const postBySlug = await getBlogPostBySlug(params.slug);
const createdAt = postBySlug?.data[0]?.internal.createdAt;
const previousPost = await getPreviousBlogPost(createdAt || null);
const previousPostSlug =
previousPost && previousPost.data && previousPost.data[0]
? previousPost.data[0].slug
: null;
const nextPost = await getNextBlogPost(createdAt || null);
const nextPostSlug =
nextPost && nextPost.data && nextPost.data[0]
? nextPost.data[0].slug
: null;
return {
props: {
post: postBySlug.data[0],
pageContext: {
previous: previousPostSlug,
next: nextPostSlug,
},
},
};
}
export async function getStaticPaths() {
const posts = await getBlogPosts(1, 10000);
const postData = posts.data;
return {
paths: postData.map((post) => ({
params: {
slug: post.slug,
},
})),
fallback: false,
};
}
export default Home;
Резюме
Теперь у нас есть функциональный блог, использующий NextJS и Flotiq HeadLess CMS :). Конечно, мы должны собрать его и развернуть на любом облачном сервисе/хостинге в следующем шаге, но это не часть данной статьи.
Если вы хотите получить такой же блог, как мы создали в этом руководстве, вы можете перейти в наш репозиторий на GitHub и нажать развернуть на выбранном облачном окружении и начать использовать его, это отлично подходит для тестирования, но для производственного использования мы рекомендуем скачать проект и изменить логотип и другие вещи в соответствии с вашими потребностями.
Это очень простой пример блога. Вы можете, например, расширить его, создав контактную форму, страницу о нас или что-то еще. Мы ждем вашего вклада в наш старт-ап :). Хорошего дня или вечера, когда бы вы это ни прочитали, и начните свой блог с FLOTIQ!