Создадим бессерверное приложение Vue.js на базе ButterCMS, для создания продающих страниц, блога и базы знаний

Создадим бессерверное приложение Vue.js на базе ButterCMS, для создания продающих страниц, блога и базы знаний

Почему Vue.js?

Эта статья написана не для того, чтобы убедить вас в том, что Vue.js самое лучшее решение и вы должны использовать его. Vue.js на сегодняшний день всего лишь прогрессивная основа для создания пользовательских интерфейсов, которая набирает популярность. Он улучшает некоторые аспекты React и Angular и позволяет создавать подключаемые компоненты, которые вы можете добавить в любой проект.

Однако а рамках этого руководства мы сосредоточимся именно на Vue.js, потому что он отлично работает с бессерверной архитектурой. Бессерверные решения становятся предпочтительной архитектурой для многих разработчиков, так как они позволяют создавать и настраивать продукты быстрее, исключая такие головные боли, как обслуживание серверов, сбои и масштабирование узких мест серверной архитектуры.

В этом учебном пособии вы узнаете, как добавить API-интерфейсы в приложение Vue.js. Эти API-интерфейсы легко внедрять, что позволит вам наслаждаться простым управлением контентом без необходимости разворачивать и поддерживать собственную инфраструктуру CMS.

В рамках этой статьи мы рассмотрим три варианта использования:

  • продающие страницы
  • базы знаний
  • блоггинг

ButterCMS

В этом руководстве для создания безсерверного приложения Vue.js используется ButterCMS. Это система управления контентом и платформа для блоггинга, которая позволяет создавать приложения на базе CMS с использованием любого языка программирования. Справедливости ради стоит заметить, что JSON API легко интегрируется с приложениями, созданными на любом языке/фреймворке.

Вы можете использовать его для создания веб-сайтов, блогов и моделирования пользовательского контента.

Создайте учетную запись бесплатно, чтобы следовать этому руководству. Здесь вы можете найти свой собственный API-ключ.

Создадим бессерверное приложение Vue.js на базе ButterCMS, для создания продающих страниц, блога и базы знаний

Итак приступим. Для начала установите пакет ButterCMS JS SDK, его мы будем использовать для запроса контента API.

npm install buttercms --save

1. Создание продающих страниц

Используя Vue и ButterCMS, вы можете создать среду, в которой любой человек в вашей команде сможет добавить контент на ваши продающие страницы, не имея абсолютно никаких технических знаний в области Web. Для этого в качестве примера мы создадим страницу тематического исследования. Используя панель управления на ButterCMS, вы можете создать «page type» под названием «Customer Case Study» и определить поля.

Как только вы это сделаете, вы можете создать свою первую страницу. Укажите имя и URL-адрес страницы с помощью панели инструментов Butter и заполните содержимое страницы. Как только вы это сделаете, API ButterCMS вернет страницу в формате JSON, которая должна выглядеть примерно так:

{
    "data": {
        "slug": "acme-co",
        "fields": {
            "facebook_open_graph_title": "Acme Co loves ButterCMS",
            "seo_title": "Acme Co Customer Case Study",
            "headline": "Acme Co saved 200% on Anvil costs with ButterCMS",
            "testimonial": "<p>We've been able to make anvils faster than ever before! - <em>Chief Anvil Maker</em></p>\r\n<p><img src=\"https://cdn.buttercms.com/NiA3IIP3Ssurz5eNJ15a\" alt=\"\" caption=\"false\" width=\"249\" height=\"249\" /></p>",
            "customer_logo": "https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV",
        }
    }
}

Затем откройте редактор кода и создайте файл buttercms.js в каталоге src.
Если у вас ещё нет существующего проекта создайте его следующими командами:

vue init webpack buttercms-project
cd buttercms-project
npm i
npm i -S buttercms
npm run dev

Теперь обновите маршруты в своем приложении

import Vue from 'vue'
import Router from 'vue-router'
import CustomersHome from '@/components/CustomersHome'
import CustomerPage from '@/components/CustomerPage'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/customers/',
      name: 'customers-home',
      component: CustomersHome
    },
    {
      path: '/customers/:slug',
      name: 'customer-page',
      component: CustomerPage
    }
  ]
})

Далее для настройки страницы клиентов, для отображения списка клиентов, мы определяем метод getpages () для получения всех страниц клиента. В components/CustomersHome.vue мы делаем:

<script>
  // import ButterCMS from 
  import { butter } from '@/buttercms'
  export default {
    name: 'customers-home',
    data() {
      return {
        page_title: 'Customers',
        // Create array to hold the pages from ButterCMS API
        pages: []
      }
    },
    methods: {
      // Get List of Customer Pages
      getPages() {
        butter.page.list('customer_case_study')
          .then((res) => {
            // console.log(res.data.data) // Check the results in the console
            this.pages = res.data.data
          })
      }
    },
    created() {
      // Fire on page creation
      this.getPages()
    }
  }
</script>

Отображение результата:

<template>
  <div id="customers-home">
    <h1>{{ page_title }}</h1>
    <div v-for="(page,index) in pages" :key="page.slug + '_' + index">
      <router-link :to="'/customers/' + page.slug">
        <div>
          <img :src="page.fields.customer_logo" alt="">
          <h2>{{ page.fields.headline }}</h2>
        </div>
      </router-link>
    </div>
  </div>
</template>

Теперь мы собираемся настроить страницу для просмотра одного клиента. Для этого в components/CustomerPage.vue мы определяем метод getPage () для получения определенной страницы клиента:
Когда вы отобразите результат, вы должны увидеть что-то вроде:

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'customer-page',
    data() {
      return {
        slug: this.$route.params.slug,
        page: {
          slug: '',
          fields: {}
        }
      }
    },
    methods: {
      getPage() {
        butter.page.retrieve('customer_case_study', this.slug)
          .then((res) => {
            console.log(res.data.data)
            this.page = res.data.data
          }).catch((res) => {
            console.log(res)
          })
      }
    },
    created() {
      this.getPage()
    }
  }
</script>

В результате получаем:

<template>
  <div id="customer-page">
    <figure>
      <img :src="page.fields.customer_logo">
    </figure>
    <h1>{{ page.fields.headline }}</h1>
    <h3>Testimonials</h3>
    <div v-html="page.fields.testimonial"></div>
    <div v-html="page.fields.body"></div>
  </div>
</template>

Теперь вы можете перейти на страницу клиента, созданную на панели управления Butter с помощью списка всех клиентских страниц или напрямую по URL-адресу.

2. Создание базы знаний

Сейчас вы познакомитесь с созданием базы знаний для своего приложения Vue.js. Для этого мы будем использовать «Content Fields» ButterCMS. Content Fields (поля контента) — это просто глобальные участки в контенте, которыми может управлять ваша команда. С помощью Content Field можно вывести практически любую информацию. Каждый Content Field имеет уникальный идентификатор для запроса.

Создание Content Field

Используя панель инструментов ButterCMS, вам нужно создать workspace (рабочее пространство) для управления Content Field. Зададим ему имя FAQ. Рабочие пространства позволят редактировать контент, не затрагивая разработку или API.

После создания Workspace, вы будете перенесены в этот workspace (рабочее пространство), кликните кнопку создать новый Content Field (поле содержимого). Выберите тип «Object» и назовите поле (Content Label) «FAQ Headline». API slug автоматически получит имя «faq_headline». Как видите не скрине, тип контента (Content Type) может быть абсолютно разный

После сохранения добавьте новый Content Field, но на этот раз выберите тип «Collection» и назовите поле «FAQ Items». Автоматически создастся API slug «faq_items». На следующем экране добавьте любые два параметра (properties) для элементов в коллекции.

Теперь вернитесь в workspace «FAQ» и добавьте нужные элементы.

Интеграция вашего приложения

Теперь, когда вы создали динамический контент, пришло время отобразить его в вашем приложении. Для этого вы получите поля с вызовом API и ссылаетесь на них в своем отображении. Вначалеа настройте маршрут на страницу часто задаваемых вопросов, для этого в редакторе кода:

router/index.js

import Vue from 'vue'
import Router from 'vue-router'

import FAQ from '@/components/FAQ'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/faq',
      name: 'faq',
      component: FAQ
    }
  ]
})

Далее создайте components/FAQ.vue с запросом получения FAQ из API:

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'faq',
    data() {
      return {
        page_title: 'FAQ',
        faq_items: []
      }
    },
    methods: {
      getFaqs() {
        butter.content.retrieve(['faq_headline', 'faq_items'])
          .then((res) => {
            console.log(res.data.data)
            this.page_title = res.data.data.faq_headline
            this.faq_items = res.data.data.faq_items
          })
      }
    },
    created() {
      this.getFaqs()
    }
  }
</script>

Результат должен быть примерно таким:

<template>
  <div id="faq">
    <h1>{{ page_title }}</h1>
    <div v-for="(faq, index) in faq_items" :key="index">
      <p>{{ faq.question }}</p>
      <p>{{ faq.answer }}</p>
    </div>
  </div>
</template>

Теперь ваша команда может обновлять значения и панели управления ButterCMS, и соответствующий контент в вашем приложении будет автоматически обновляться.

2. Создание блога

Теперь мы займемся добавлением движка блога. Вы можете быстро создать блог с поддержкой CMS с помощью Vue.js.

Отображение статей

Мы начнем с создания маршрута блога с помощью vue-router. Для отображения статей, мы создаем простой маршрут /blog в нашем приложении и получаем сообщения из блога, а также создадим маршрут /blog/:slug для обработки отдельных сообщений.

router/index.js:

import Vue from 'vue'
import Router from 'vue-router'
import BlogHome from '@/components/BlogHome'
import BlogPost from '@/components/BlogPost'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/blog/',
      name: 'blog-home',
      component: BlogHome
    },
    {
      path: '/blog/:slug',
      name: 'blog-post',
      component: BlogPost
    }
  ]
})

Для создания главной страницы Home вашего блога создайте components/BlogHome.vue, на ней будут отображаться последние статьи

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'blog-home',
    data() {
      return {
        page_title: 'Blog',
        posts: []
      }
    },
    methods: {
      getPosts() {
        butter.post.list({
          page: 1,
          page_size: 10
        }).then((res) => {
          // console.log(res.data)
          this.posts = res.data.data
        })
      }
    },
    created() {
      this.getPosts()
    }
  }
</script>

На выходе должно получиться следующее:

<template>
  <div id="blog-home">
      <h1>{{ page_title }}</h1>
      <!-- Create v-for and apply a key for Vue. Example is using a combination of the slug and index -->
      <div v-for="(post,index) in posts" :key="post.slug + '_' + index">
        <router-link :to="'/blog/' + post.slug">
          <article class="media">
            <figure>
              <!-- Bind results using a ':' -->
              <!-- Use a v-if/else if their is a featured_image -->
              <img v-if="post.featured_image" :src="post.featured_image" alt="">
              <img v-else src="http://via.placeholder.com/250x250" alt="">
            </figure>
            <h2>{{ post.title }}</h2>
            <p>{{ post.summary }}</p>
          </article>
        </router-link>
      </div>
  </div>
</template>

Далее создайте components/BlogPost.vue, это будет вашей отдельной страницей блога.

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'blog-post',
    data() {
      return {
        post: {}
      }
    },
    methods: {
      getPost() {
        butter.post.retrieve(this.$route.params.slug)
          .then((res) => {
            // console.log(res.data)
            this.post = res.data
          }).catch((res) => {
            console.log(res)
          })
      }
    },
    created() {
      this.getPost()
    }
  }
</script>

Получаем:

<template>
  <div id="blog-post">
    <h1>{{ post.data.title }}</h1>
    <h4>{{ post.data.author.first_name }} {{ post.data.author.last_name }}</h4>
    <div v-html="post.data.body"></div>

    <router-link v-if="post.meta.previous_post" :to="/blog/ + post.meta.previous_post.slug" class="button">
      {{ post.meta.previous_post.title }}
    </router-link>
    <router-link v-if="post.meta.next_post" :to="/blog/ + post.meta.next_post.slug" class="button">
      {{ post.meta.next_post.title }}
    </router-link>
  </div>
</template>

На этом этапе ваше приложение вытаскивает все статьи из блога, позволяя вам перемещаться между ними. Если вы протестировали, то уже заметили, что кнопки навигации next/previous не работают. Почему? При использовании маршрутов с параметрами, когда пользователь переходит от /blog/foo к /blog/bar, один и тот же экземпляр компонента используется повторно.

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

Для этого есть исправление. Нам нужно посмотреть объект $route и вызвать getPost () при изменении маршрута. Для этого обновим раздел сценария в components/BlogPost.vue :

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'blog-post',
    data() {
      return {
        post: {}
      }
    },
    methods: {
      getPost() {
        butter.post.retrieve(this.$route.params.slug)
          .then((res) => {
            // console.log(res.data)
            this.post = res.data
          }).catch((res) => {
            console.log(res)
          })
      }
    },
    watch: {
      $route(to, from) {
        this.getPost()
      }
    },
    created() {
      this.getPost()
    }
  }
</script>


Теперь ваше приложение имеет рабочий блог, контент которого легко изменяется из панели управления CMS.

Также для фильтрации и размещения контента в своем блоге с категориями, тегами и авторами вы можете использовать API. Фактически, с точки зрения управления различными параметрами вашего блога, с помощью API вы можете сделать ещё очень много, например добавить разметку RSS, Atom, создать Sitemap, а также добавить стили CSS контента.

Послесловие

В этой статье наглядно показано, как легко создать бессерверное приложение Vue.js с поддержкой CMS. Прогрессивная инфраструктура для создания пользовательских интерфейсов Vue, довольно быстро реализуется, что экономит ваше время разработки.

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

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

Перевод статьи автора Jake Lumetta: Why and How You Should Build a Serverless CMS-powered Vue.js App