INTEGRITY Документация

Создайте блог с помощью Nuxt.js и Sanity.io на Cloudflare Pages

В этом руководстве вы создадите блог с помощью Nuxt.js и Sanity.io и развернете его в Cloudflare Pages. Nuxt.js представляет собой мощный генератор статических сайтов, построенный на фронтенд-фреймворке Vue.js. Sanity.io представляет собой headless CMS для управления данными приложения без необходимости поддерживать базу данных.

Предварительные требования

Создание нового проекта Sanity

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

Установка Sanity и настройка набора данных

Создайте новый проект Sanity, установив @sanity/cli клиент из npm и выполнив sanity init в терминале:

npm i @sanity/cli
npx sanity init

При создании проекта Sanity можно использовать одну из готовых схем. Схемы описывают структуру данных в наборе данных Sanity. Если вы начинаете совершенно новый проект, можно инициализировать схему с нуля, но сейчас выберите Блог схема.

Изучение схемы

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

cd my-sanity-project
npx sanity start

В Sanity Studio можно создавать новые записи для вашего набора данных. При локальном запуске Studio по умолчанию доступна по адресу localhost:3333, перейдите туда и создайте запись автора. Здесь также можно создавать посты блога.

Создание записи блога в панели управления проекта Sanity

Развертывание вашего набора данных

Когда будете готовы развернуть студию, выполните sanity deploy чтобы выбрать уникальный URL-адрес для своей студии. Это означает, что вы (или любой другой пользователь, которого вы пригласите для управления блогом) сможете открывать студию по адресу yoururl.sanity.studio домен.

npx sanity deploy

После развёртывания Sanity Studio:

  1. Откройте панель управления Sanity (manage.sanity.io).
  2. Найдите свой проект.
  3. Выберите API.
  4. Добавить http://localhost:3000 как разрешённый источник CORS для вашего проекта.

Это означает, что запросы к вашему набору данных Sanity от приложения Nuxt будут добавлены в список разрешённых.

Настройки CORS проекта Sanity

Создание нового проекта Nuxt.js

Далее создайте проект Nuxt.js. В новом терминале используйте create-nuxt-app чтобы настроить новый проект Nuxt:

npx create-nuxt-app blog

Важно убедиться, что вы выбрали режим рендеринга Universal (SSR / SSG) и целью развёртывания Статический (статический/JAMStack-хостинг), в процессе настройки.

После того как вы завершите проект, cd в новый проект и запустите локальный сервер разработки командой yarn dev (или, если в качестве менеджера пакетов вы выбрали npm, npm run dev):

cd blog
npm run dev

Интеграция Sanity.io

После того как вы настроите приложение Nuxt.js, добавьте Sanity @sanity/nuxt плагин в проект Nuxt:

npm i @nuxtjs/sanity @sanity/client

Чтобы настроить плагин в приложении Nuxt.js, укажите необходимые параметры конфигурации. Проще всего скопировать sanity.json папку из вашей студии в каталог приложения (хотя есть и другие способы: обратитесь к @nuxt/sanity документация.

Добавление sanity.json
cp ../my-sanity-project/sanity.json .

Наконец, добавьте @nuxtjs/sanity как модуль сборки в конфигурации Nuxt:

nuxt.config.js
{
	buildModules: ["@nuxtjs/sanity"];
}

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

После настройки Sanity в приложении можно начать использовать его для отображения блога. Далее вы настроите несколько страниц для получения данных из Sanity API и их отображения. Если вы не знакомы с Nuxt, рекомендуется сначала изучить Руководство по Nuxt, который познакомит вас с основами разработки приложений на Nuxt.

Настройка главной страницы

Для начала обновите index страница, которая будет отрендерена при переходе на корневой маршрут (/). В pages/index.vue:

pages/index.vue
<template>
	<div class="container">
		<div>
			<h1 class="title">My Blog</h1>
		</div>
		<div class="posts">
			<div v-for="post in posts" :key="post._id">
				<h2><a v-bind:href="post.slug.current" v-text="post.title" /></h2>
			</div>
		</div>
	</div>
</template>

<script>
	import { groq } from "@nuxtjs/sanity";

	export default {
		async asyncData({ $sanity }) {
			const query = groq`*[_type == "post"]`;
			const posts = await $sanity.fetch(query);
			return { posts };
		},
	};
</script>

<style>
	.container {
		margin: 2rem;
		min-height: 100vh;
	}
	.posts {
		margin: 2rem 0;
	}
</style>

Vue SFC, или однофайловые компоненты, уникальная функция Vue, которая позволяет объединить JavaScript, HTML и CSS в одном файле. В pages/index.vue, template тег, который представляет компонент Vue.

Важно: v-for используется как директива, указывающая Vue отрисовывать HTML для каждого post в массиве posts:

Изучение директивы v-for
<div v-for="post in posts" :key="post._id">
	<h2><a v-bind:href="post.slug.current" v-text="post.title" /></h2>
</div>

Чтобы заполнить posts массив, asyncData функция, которую предоставляет Nuxt для выполнения асинхронных вызовов (например, сетевых запросов) для заполнения данных страницы.

$sanity объект предоставляется интеграцией Nuxt и Sanity.js как способ отправлять запросы к набору данных Sanity. Вызывая $sanity.fetch, передав запрос, вы можете получить конкретные данные из набора данных Sanity и вернуть их в качестве данных вашей страницы.

Если вы раньше не использовали Sanity, вы, вероятно, не знакомы с GROQ, языком запросов GRaph Oriented Query, который Sanity предоставляет для работы с вашим набором данных. GROQ представляет собой мощный язык, позволяющий указать Sanity API, какие данные вы хотите получить из набора данных. В нашем первом запросе мы попросим Sanity получить все объекты в наборе данных с _type значение post:

Базовый запрос GROQ
const query = groq`*[_type == "post"]`;
const posts = await $sanity.fetch(query);

Настройка страницы записи блога

Наш index страница выводит ссылку для каждой записи блога в нашем наборе данных, используя slug значение, чтобы задать URL-адрес записи блога. Например, если создать запись блога с названием "Hello World" и задать slug равным hello-world, моё приложение Nuxt должно уметь обрабатывать запрос к странице /hello-world, и получить соответствующую запись блога из Sanity.

В Nuxt есть встроенная поддержка таких страниц: для этого нужно создать новый файл в pages в формате _slug.vue. В asyncData функции вашей страницы вы можете использовать params аргумент для ссылки на slug:

pages/_slug.vue
<script>
	export default {
		async asyncData({ params, $sanity }) {
			console.log(params); // { slug: "hello-world" }
		},
	};
</script>

Учитывая это, можно собрать pages/_slug.vue чтобы принять входящий slug значение, выполнить запрос к Sanity для поиска соответствующей записи блога и отрендерить post заголовок для записи блога:

pages/_slug.vue
<template>
	<div class="container">
		<div v-if="post">
			<h1 class="title" v-text="post.title" />
			<div class="content"></div>
		</div>
		<h4><a href="/">← Go back</a></h4>
	</div>
</template>

<script>
	import { groq } from "@nuxtjs/sanity";

	export default {
		async asyncData({ params, $sanity }) {
			const query = groq`*[_type == "post" && slug.current == "${params.slug}"][0]`;
			const post = await $sanity.fetch(query);
			return { post };
		},
	};
</script>

<style>
	.container {
		margin: 2rem;
		min-height: 100vh;
	}

	.content {
		margin: 2rem 0;
		max-width: 38rem;
	}

	p {
		margin: 1rem 0;
	}
</style>

Например, при переходе по адресу /hello-world, Nuxt возьмёт входящий slug hello-world, и выполните GROQ запрос к Sanity для получения всех объектов с _type post, а также slug, который соответствует значению /hello-world. Из этого набора можно получить первый объект массива, используя оператор индекса массива, знакомый по JavaScript: [0]) и установите его как post в данных вашей страницы.

Рендеринг контента для записи блога

Вы выполнили рендеринг post заголовок для нашего блога, но у вас всё ещё отсутствует содержимое самой записи блога. Чтобы отобразить его, импортируйте sanity-blocks-vue-component пакет, который использует данные Sanity Portable Text формат и отображает его как компонент Vue.

Сначала установите npm-пакет:

npm i sanity-blocks-vue-component

После установки пакета создайте plugins/sanity-blocks.js, который импортирует компонент и зарегистрирует его как Vue-компонент block-content:

plugins/sanity-blocks.js
import Vue from "vue";
import BlockContent from "sanity-blocks-vue-component";
Vue.component("block-content", BlockContent);

В конфигурации Nuxt, nuxt.config.js, импортируйте этот файл в рамках plugins директиву:

nuxt.config.js
{
	plugins: ["@/plugins/sanity-blocks.js"];
}

В pages/_slug.vue, теперь вы можете использовать <block-content> компонент для отображения содержимого. Это пользовательский HTML компонент, который принимает три аргумента: :blocks, который указывает, что рендерить (в нашем случае, child), v-for, который принимает итератор, указывающий, откуда получить child из (в нашем случае, post.body), и :key, который помогает Vue отслеживать состояние рендеринга указав уникальное значение для каждого поста, а именно _id значение.

pages/_slug.vue
<template>
	<div class="container">
		<div v-if="post">
			<h1 class="title" v-text="post.title" />
			<div class="content">
				<block-content
					:blocks="child"
					v-for="child in post.body"
					:key="child._id"
				/>
			</div>
		</div>
		<h4><a href="/">← Go back</a></h4>
	</div>
</template>

<script>
	import { groq } from "@nuxtjs/sanity";

	export default {
		async asyncData({ params, $sanity }) {
			const query = groq`*[_type == "post" && slug.current == "${params.slug}"][0]`;
			const post = await $sanity.fetch(query);
			return { post };
		},
	};
</script>

<style>
	.container {
		margin: 2rem;
		min-height: 100vh;
	}

	.content {
		margin: 2rem 0;
		max-width: 38rem;
	}

	p {
		margin: 1rem 0;
	}
</style>

В pages/index.vue, вы можете использовать block-content компонент для вывода краткого содержания, который берет первый блок содержимого записи блога и отображает его:

pages/index.vue
<template>
	<div class="container">
		<div>
			<h1 class="title">My Blog</h1>
		</div>
		<div class="posts">
			<div v-for="post in posts" :key="post._id">
				<h2><a v-bind:href="post.slug.current" v-text="post.title" /></h2>
				<div class="summary">
					<block-content
						:blocks="post.body[0]"
						v-bind:key="post.body[0]._id"
						v-if="post.body.length"
					/>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
	import { groq } from "@nuxtjs/sanity";

	export default {
		async asyncData({ $sanity }) {
			const query = groq`*[_type == "post"]`;
			const posts = await $sanity.fetch(query);
			return { posts };
		},
	};
</script>

<style>
	.container {
		margin: 2rem;
		min-height: 100vh;
	}
	.posts {
		margin: 2rem 0;
	}
	.summary {
		margin-top: 0.5rem;
	}
</style>

В схему блога можно добавить ещё много других элементов. В качестве упражнения попробуйте один из следующих вариантов, чтобы углубить понимание работы с headless CMS:

Публикация с помощью Cloudflare Pages

Публикация проекта с помощью Cloudflare Pages состоит из двух шагов: сначала вы отправляете проект в GitHub, а затем в панели управления Cloudflare Pages создаёте новый проект на основе этого репозитория GitHub. Pages разворачивает новую версию сайта при каждой публикации и даже создаёт превью-деплои при открытии каждого нового pull request.

Чтобы отправить проект в GitHub, создать новый репозиторий, и следуйте инструкциям, чтобы отправить локальный репозиторий Git в GitHub.

После того как вы отправите проект в GitHub, разверните сайт в Pages:

  1. На панели управления Cloudflare перейдите к разделу Workers & Pages страницу.

    Перейдите в Workers & Pages ↗
  2. Выберите Создать приложение > Pages > Импорт существующего репозитория Git.

  3. Выберите созданный вами новый репозиторий GitHub и нажмите Начало настройки.

  4. В Настройка сборок и деплоев разделе, в Настройки сборки > Framework preset, выберите Nuxt. Pages автоматически задаст правильные значения полей.

После развёртывания сайта вы получите уникальный URL-адрес для его просмотра в продакшене.

Чтобы автоматически развертывать проект при изменении данных Sanity.io, можно использовать Deploy Hooks. Создайте новый URL-адрес Deploy Hook в своем Проект Pages > Настройки. На странице настроек проекта Sanity найдите Webhooks раздел и добавьте URL-адрес Deploy Hook, как показано ниже:

Добавление URL-адреса Deploy Hook в панели управления Sanity

Теперь при изменении набора данных Sanity.io сервис Sanity отправляет запрос на уникальный URL-адрес Deploy Hook, что запускает новое развёртывание Cloudflare Pages. Благодаря этому приложение Pages остаётся актуальным по мере добавления новых записей блога или редактирования существующих.

Заключение

После выполнения этого руководства вы успешно развернули собственный блог на основе Nuxt, Sanity.io и Cloudflare Pages. Исходный код обеих кодовых баз можно найти на GitHub:

Если это руководство было вам полезно, возможно, вас заинтересует, как использовать Cloudflare Workers, нашу мощную платформу serverless-функций, для расширения возможностей существующего сайта. Ознакомьтесь с Руководство по созданию API для внешнего интерфейса с помощью Pages Functions чтобы узнать больше.