Markdown стал основным элементом моего рабочего процесса как разработчика и создателя контента. Он быстро пишется, гибок благодаря своим функциям и имеет легко запоминающийся синтаксис.

С использованием Реагировать на уценкумы собираемся создать пользовательские компоненты React (в Next.js приложение) с использованием проанализированного уценки, полученного из безголовой CMS. Таким образом, мы сможем довольно легко использовать передовые функции, такие как Следующее изображение в теле нашего Markdown. Таким образом, мы можем брать динамический контент и формировать его так, как мы хотим, улучшая производительность, доступность и общее взаимодействие с пользователем.

mdn в html

В этой статье представлены Шаблон портфолио разработчика Next.js я построил с космический. Вы можете следить, посетив Страница шаблона приложения и импортировать шаблон в свой собственный Cosmic Bucket (завести аккаунт если вы хотите следовать этому пути и еще не сделали его). Или просмотрите исходный код если вы предпочитаете следовать своему собственному приложению.


Краткий обзор React Markdown

React Markdown — это компонент React для рендеринга уценки, который позволяет создавать и отображать пользовательские компоненты вместо стандартных компонентов HTML. Это безопасно по умолчанию (нет dangerouslySetInnerHTML) и позволяет использовать широкий спектр плагины из примечания чтобы увеличить вашу уценку.

Схема потока архитектуры реакции уценки

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

  1. Содержимое уценки анализируется и превращается в синтаксическое дерево уценки.
  2. Синтаксическое дерево уценки преобразуется в синтаксическое дерево HTML посредством замечание
  3. Синтаксическое дерево HTML преобразуется с помощью повторно рекламироватьи визуализируются в компоненты React.


Установка пакетов

Чтобы использовать react-markdown, нам нужен только сам пакет.

pnpm add react-markdown
## or
npm install react-markdown
## or
yarn add react-markdown
Войти в полноэкранный режим

Выйти из полноэкранного режима

Чтобы получить наши данные из Cosmic, мы можем установить модуль Cosmic NPM.

pnpm add cosmicjs
## or
npm install cosmicjs
## or
yarn add cosmicjs
Войти в полноэкранный режим

Выйти из полноэкранного режима


Получение нашего контента Markdown из безголовой CMS

В этом примере мы извлекаем контент уценки из Cosmic Объект это будет основной текст статьи. В каталоге pages нашего приложения Next.js убедитесь, что у вас есть [slug].jsx файл, созданный в папке с именем posts, articles или что угодно.

Мы можем импортировать cosmicjs package, задайте переменные окружения, затем напишите две функции, которые будут получать данные с нашей приборной панели Cosmic.

const Cosmic = require('cosmicjs')
const api = Cosmic()

const bucket = api.bucket({
  slug: process.env.COSMIC_BUCKET_SLUG,
  read_key: process.env.COSMIC_READ_KEY,
})

export async function getAllPostsWithSlug() {
  const params = {
    query: { type: 'posts' },
    props: 'title,slug,metadata,created_at',
  }
  const data = await bucket.getObjects(params)
  return data.objects
}

export async function getPostAndMorePosts(slug, preview) {
  const singleObjectParams = {
    query: { slug: slug },
    ...(preview && { status: 'any' }),
    props: 'slug,title,metadata,created_at',
  }
  const moreObjectParams = {
    query: { type: 'posts' },
    ...(preview && { status: 'any' }),
    limit: 3,
    props: 'title,slug,metadata,created_at',
  }

  try {
    const data = await bucket.getObjects(singleObjectParams)
    const moreObjects = await bucket.getObjects(moreObjectParams)
    const morePosts = moreObjects.objects
      ?.filter(({ slug: object_slug }) => object_slug !== slug)
      .slice(0, 2)
    return {
      post: data?.objects[0],
      morePosts,
    }
  } catch (error) {
    if (is404(error)) return
    throw error
  }
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

В рамках нашего [slug].jsx файл, мы можем позвонить getStaticProps() а также getStaticPaths() получить данные, а затем передать их нашему Post составная часть.

// pages/posts/[slug].jsx

const Post = ({ post }) => {
  return (
    <>
      <article>
        <PostBody content={post.metadata.content} />
      </article>
    </>
  )
}
export default Post

export async function getStaticProps({ params, preview = null }) {
  const data = await getPostAndMorePosts(params.slug, preview)

  return {
    props: {
      preview,
      post: {
        ...data.post,
      },
      morePosts: data.morePosts || [],
    },
  }
}

export async function getStaticPaths() {
  const allPosts = (await getAllPostsWithSlug()) || []
  return {
    paths: allPosts.map(post => `/posts/${post.slug}`),
    fallback: true,
  }
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

Теперь, когда мы настроили саму страницу, давайте погрузимся в нашу PostBody компонент, где мы будем использовать react-markdown для рендеринга нашего контента.


Внедрение React Markdown

В рамках нашего PostBody мы можем импортировать и использовать ReactMarkdown Составная часть. Мы просто импортируем пакет и оборачиваем наше содержимое в ReactMarkdown составная часть.

import ReactMarkdown from 'react-markdown'

const PostBody = ({ content }) => {
  return (
    <div className="max-w-2xl mx-auto">
      <ReactMarkdown>
        {content}
      </ReactMarkdown>
    </div>
  )
}
export default PostBody
Войти в полноэкранный режим

Выйти из полноэкранного режима


Создание пользовательских компонентов

Кроме того, мы можем создавать собственные компоненты. Для этого мы создадим components объект над нашим PostBody компонент и передать его в ReactMarkdown составная часть.

При создании пользовательских компонентов ключ будет HTML-эквивалентом содержимого, которое мы пишем в уценке. Параметр будет тем, что вы хотите отобразить как элемент HTML, и будет иметь доступ к свойствам этого элемента. Например, a элемент даст нам доступ к href а также children и img ярлык src а также alt.

JSX, который вы пишете в этих функциях, вернет предоставленный элемент. Вы можете написать что-то вроде h1: h1 => {return (<h2>{h1.children}</h2>)} а ты будешь рендерить h2 элементы для каждого h1 написано в уценке.

import ReactMarkdown from 'react-markdown'

const components = {
  a: a => {
    return (
      <a href={a.href} rel="noopener noreferrer" target="_blank">
        {a.children}
      </a>
    )
  },
}

const PostBody = ({ content }) => {
  return (
    <div className="max-w-2xl mx-auto">
      <ReactMarkdown
        components={components}
      >
        {content}
      </ReactMarkdown>
    </div>
  )
}
export default PostBody
Войти в полноэкранный режим

Выйти из полноэкранного режима

До сих пор моим любимым вариантом использования была реализация Next Image для оптимизированных размеров изображений и лучшего времени загрузки страницы.

Без использования Next Image наличие большого количества изображений в нашей уценке потребует загрузки всех изображений при запросе страницы. Это медленно и негативно влияет на пользовательский опыт и оценки маяков.

Когда я обновляю страницу, все изображения загружаются сразу. Ой!

Загрузка всех изображений на веб-страницу без ленивой загрузки

Давайте улучшим это! импорт Image из next/imageзатем создайте пользовательский img компонент внутри components объект. Помните, что у нас есть доступ к некоторым стандартным реквизитам с этими компонентами, поэтому мы можем просто взять src а также alt от img. Мы передаем их в нашу Image компонент, написанный на нашем JSX, определяющий набор height а также widthболее низкий quality к размеру файла и layout из responsive для предоставления масштабированных изображений в соответствии с размером экрана, гарантируя, что небольшие устройства не получат файлы излишне большого размера.

import ReactMarkdown from 'react-markdown'
import Image from 'next/image'

const components = {
  a: a => {
    return (
      <a href={a.href} rel="noopener noreferrer" target="_blank">
        {a.children}
      </a>
    )
  },
  img: img => {
    return (
      <Image
        src={img.src}
        alt={img.alt}
        width={400}
        height={300}
        quality={50}
        layout="responsive"
        objectFit="contain"
        objectPosition="center"
      />
    )
  },
}

const PostBody = ({ content }) => {
  return (
    <div className="max-w-2xl mx-auto">
      <ReactMarkdown
        components={components}
      >
        {content}
      </ReactMarkdown>
    </div>
  )
}
export default PostBody
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

Загрузка изображений на веб-страницу с помощью Next Image и отложенной загрузки

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

Очень важно иметь возможность создавать собственные компоненты React для уценки, а с помощью react-markdown мы можем добиться этого всего за несколько строк кода. Здесь мы достигаем повышения производительности, повышения безопасности канала и общих расширенных возможностей для наших данных уценки. Помимо улучшений в нашем приложении, этот компонент очень прост в использовании и позволяет нам унифицированные js (дает нам сверхспособности!).

Присоединяйтесь к нам! Вы можете настроиться на наше новое шоу Время сборкигде мы освещаем такие темы, как безголовая CMS, Next.js, React и много много более.