56
58

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue.jsとButterCMSとNetlifyでSPAブログを構築する

Posted at

初めに

ブログを始めようと思いいろいろ調べてみたところ、アメブロやはてなブログからWordPressなどなどいろいろでてきて悩みました・・・。

悩みに悩んだ結果、Vue.js公式が公開しているVue.jsとButterCMSの組み合わせでSPAブログは構築し、リリースはNetlifyを利用したいと思います。

公開したブログはこちら

ButterCMS

https://buttercms.com/

全然日本語の記事が見つからないのですが、どうやらSaaS(Software as a Service)の1つで、ウェブサイトの構築をサポートする優れたヘッドレス CMSだそうです。

※グーグルの記事を参考にしました

ButterCMSでブログの記事を書き、Vue.jsでAPIを叩き記事一覧・記事詳細を表示する構成です。

構築手順

1.ButterCMS登録

登録方法は公式サイトにアクセスし、緑色の「Try it for FREE」と書かれたボタンをクリック。

スクリーンショット 2018-05-29 21.43.42.png

登録方法を選択するモーダルが開きます。今回自分はGitHubを選択。

スクリーンショット 2018-05-29 21.44.29.png

ログインに成功するとダッシュボードが表示されます。

スクリーンショット 2018-05-29 21.46.17.png

Blog Postsを確認するとサンプルの記事がすでにあります。

スクリーンショット 2018-05-29 21.48.45.png

2.アプリケーションの構築

ButterCMSにあるサンプルの記事を一覧で取得、詳細で表示するVue.jsアプリケーションを構築していきます。

準備

$ npm init -y
$ npm i vue vue-router buttercms --save
$ npm i css-loader vue-loader@^14.2.2 vue-template-compiler webpack webpack-cli webpack-dev-server --save-dev

vue-loaderは最新版の15が安定していないのでバージョンを14.2.2にしています。

buttercmsというパッケージでbutterCMSからブログを取得します。

コーディング

webpack.config.js
module.exports = {
  entry: './src/js/app.js',
  output: {
    path: __dirname,
    filename: './src/js/bundle.js'
  },
  resolve: {
    alias: {
      vue: 'vue/dist/vue.esm.js',
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      }
    ]
  }
};

webpack.config.jsは以前作ったものを参考にしました。

index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Blog</title>
</head>
<body>
  <main id="app">
    <router-view></router-view>
  </main>
  <script src="js/bundle.js"></script>
</body>
</html>

index.htmlはビルドされたbundle.jsの読み込みと、vue-routerようにrouter-viewタグの指定をしています。

app.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from './components/Home.vue';
import Detail from './components/Detail.vue';

Vue.use(Router);

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      component: Home
    },
    {
      path: '/blog/:slug',
      component: Detail
    },
  ]
});

new Vue({
  el: '#app',
  router: router,
});

app.jsはvue-routerの設定と、ブログ一覧URLとブログ詳細URLを指定しています。

ブログの詳細はブログごとにURLは書かず、動的に取得するため一つだけ指定しています。

buttercms.js
import Butter from 'buttercms';

export default Butter(YOUR_API_KEY);

butterCMS利用のための初期設定です。

API KEYはsettingから確認できます。

スクリーンショット 2018-05-31 20.39.02.png
Home.vue
<template>
  <div id="blog-home">
    <h1>{{ page_title }}</h1>
    <div v-for="(post,index) in posts" :key="post.slug + '_' + index">
      <router-link :to="'/blog/' + post.slug">
        <article class="media">
          <figure>
            <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>

<style scoped>
  article {
    width: 400px;
  }
  img {
    width: 100%;
  }
</style>

<script>
  import butter from './../buttercms.js';

  export default {
    data() {
      return {
        posts: []
      }
    },
    methods: {
      getPosts() {
        butter.post.list({
          page: 1,
          page_size: 10
        }).then((res) => {
          this.posts = res.data.data
        })
      }
    },
    created() {
      this.getPosts();
    }
  }
</script>

ブログ一覧のVueコンポーネントです。

butter.post.list({page: 1,page_size: 10})で取得して、表示しています。

Detail.vue
<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>

<script>
  import butter from './../buttercms.js';

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

ブログ詳細のVueコンポーネントです。

butter.post.retrieve(this.$route.params.slug)でブログの詳細を取得して、表示しています。

ビルド

ディレクトリ構成は下記になってます。

スクリーンショット 2018-05-31 20.43.07.png

開発中はwebpack-dev-serverをインストールしているので、これを利用します。

$ webpack-dev-server

開発サーバーをたちあげ、http://localhost:8080/にアクセス。

スクリーンショット 2018-05-31 20.46.43.png

すると、このようにサンプルの記事が表示されます。

クリックして記事の詳細に遷移すると(URLはhttp://localhost:8080/blog/example-post)下記のように表示されます!

screencapture-localhost-8080-blog-example-post-2018-05-31-20_51_29.png

3. リリース

今回はNetlifyを利用してリリースします。

Netlifyの詳細や設定は下記記事に書いてあります。

vue-cliでwebアプリケーションを作って、Netlifyを使って無料で爆速でリリースした話

今回特別に指定したのは、Build commandにnpm run buildを指定し、Publish directoryは空にしました。

package.jsonのscriptsには"build": "webpack"を指定しているので、実際はwebpackコマンドが実行されています。

終わりに

自分で作る場合DB用意しなきゃかなーと思っていたのですが、こんな手法が取れるとは・・・!

次はSSRに挑戦してみます!

56
58
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
58

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?