LoginSignup
11
11

More than 5 years have passed since last update.

Contentful+Nuxtでブログ作成 オリジナル記事投稿画面に苦労

Posted at

あらまし

結構長くはてなブログにお世話になっていたが、

  • 適当に運営していたのでタグやカテゴリ管理ができていない
  • scrapbox.ioのUI, UXに魅力を感じ、パク…インスパイアされた
  • 自身で開発したい気分になった

などの理由でブログを作ろうと思い立った。

なお、完成品はこちら

スクリーンショット 2019-03-09 19.20.23.png

投稿画面

スクリーンショット 2019-03-09 19.32.07.png

HashMikiri

欲しかった仕様

  • scrapboxに影響を受けたハードルの低い投稿画面
    • 入力欄は本文のみで、一行目をタイトルと認識、#に続く文字をハッシュタグと認識
    • その他はMarkdownに準ずる
  • ハッシュタグによる検索機能
    • タグで検索し、引っかかった記事がズラッと並ぶ
  • ハッシュタグ自動リンク機能

欲しかった仕様から逆算した仕様

  • サーバーサイドの機能はContentfulにお任せ
    • Headless CMSと呼ばれる、CMSから見た目部分を取っ払いデータ部分に特化した仕様
    • 最初はFirebaseでやろうとしたけど、DB設計が大変そうなので撤退
  • フロント側はNuxt.jsを採用
    • VueJSのコンポーネントで組み立てるフレームワーク
    • 単純に使い慣れていたので
  • herokuにデプロイ
    • 単純に使い慣れていたので

Contentful+Nuxtで小手調べ

まずは存在する記事を全表示するトップページを作ろうと思ったが、

公式DocのNuxtの部を見ればそこはなんとかなった。

なお、自分の環境だと npm i -g contentful-cli がエラーで入らなかったので、

Spaceの作成はContentfulのWebサイトを使って行った。

ざっと手順

  • nuxtのテンプレートを展開
  • Contentfulに接続するjsライブラリをインストール(npm install --save contentful)
  • ./plugins/contentful.jsに公式Doc通りの記述をすることでnpmのcontentful.jsをラップ。たぶんセキュリティ的にこうしている
  • .contentful.jsonにトークンとか書く(トークンは本来cliで取れるようだが、自分はWebから入手)
  • ./nuxt.config.jsで今のjsonを読むようにする。たぶんセキュリティ
  • nuxtのpagesディレクトリで、
    • script部でasyncData ({env})内でclient.getEntriesすることでpostsが返ってくる(公式のDocではPersonも取得している)
    • postsをテンプレート部でv-for="post in posts"してpostごとにアクセス可能に
    • {{post.fields.title}}でタイトルを表示

注意点

そんなに難しくないが、titleがpostオブジェクト直下ではなく、post.fields.titleに入っているのでちょい迷った。

他にもbody(本文)やtagsなど、Contentfulで自分で設定したフィールドはfieldsに入る。

idやcreateAtなど、Contentful側が自動で作るフィールドはsysに入るようだ。

今回の仕様に即したフィールド構成でもう一回

blogのテンプレートにはblogPostとuserの2つのContent Modelがあり、

blogPostの中にはheroImageなども入っていたのだが、今回のブログ仕様では使わないので新たなContent Modelを作った。

下のように、簡単に作れる。

スクリーンショット 2019-03-09 18.16.29.png

Dateはいるかなと思って作ったがcreateAtを利用することにしたので削除した。

で、nuxtの方からも新しいContent Modelを呼び出すように変更。

その際、

  • ~/
  • ~/{tag}
  • ~/{tag}/{page}

など複数のURLからAPIを呼ぶことになるので、リスト表示用componentを作成した。

あとこの辺で見た目部分をBootstrap Vueにした。

注意点

componentではasyncData ({env})は使えなかった…

本来componentにtagとpageを渡すとAPIを叩いてくれるというふうにしたかったところ、

pageのほうでAPIを叩いてpostsを取得し、postsをcomponentに投げるという方式になったが、

結局同じような処理(API叩く)を3通り書いてしまったので反省点。

いよいよ投稿画面

ここまでは壮大な前フリで、ここから投稿画面制作に入る。

まずいきなりつまずいたのは、APIはAPIでもコンテンツ取得用とマネージ用ではものが違うということ。

npm i contentfulで入るやつはContent Delivery APIしか触れないらしい。

つまりブログポストしたかったら、Ajaxで直にAPIを触るしかないのだ。

axiosを導入し(過去に使用したことがあったため)頑張って叩いた。

おそらくこんな感じになろうという例がこれ

postToContentful(){

        axios.post( `https://api.contentful.com/spaces/${space}/environments/${env}/entries` , {
          fields: {
            title:{"en-US": "タイトル"},
            body: {"en-US": "コンテンツのボディ"},
            tags: {"en-US": ["タグ", "タグ2"]},

          }
        }, {
          headers: {
            "Authorization": `Bearer ${token}`,
            "Content-Type": 'application/vnd.contentful.management.v1+json',
            "X-Contentful-Content-Type": `${contentType}`
          }
        })
          .then(response => {
            console.log(response);
          }).catch(error => {
            console.log(error);
          })
      }

このpostToContentful()を呼び出すことでテスト記事が投稿される…はず!

注意点

  • ローカライズのためだと思うが、タイトルなどは"en-US"の中に書かねばならない。USじゃないけどJaにする方法が分からないので諦めた
  • タグなどリストのフィールドは{[{"en-US": "タグ1"},{"en-US": "タグ1"}]ではなく、{"en-US": ["タグ1","タグ2"]}
  • URLのenvをWebから探すのに手こずったので、APIを叩いて確認した。初期設定では"master"だと思う

Oauth

この時点ではパスワードをハードコーディングすることで投稿制限を実現していたのだが、

やはりセキュリティ的に不安なのでOauthを導入してみた。

注意点:contentfulのOauth Appは「ユーザー」画面から作る。行き方が分からなくて迷った。

所定のページにアクセスするとhttp://localhost:8080/my-app/#access_token=$CONTENT_MANAGEMENT_API_ACCESS_TOKENのような形でアクセストークンが得られる。

これで楽勝だぜ! と思ったら思わぬところでつまずいた。

location.hashでURLのハッシュ部分を取ろうと思ったら、locationがundefined

公式Docにも説明があるが、SSRだとその時点ではlocationは存在しないので、undefinedになってしまう。

結局、nuxtのページから

    <no-ssr>
      <MyForm />
    </no-ssr>

のようにMyFormを呼び出す(その際no-ssrでくくる)ことで事態を打開できた。

ひとまず完成

デザインとかRSSとかちまちまやることはあったのだが、ひとまず基本部分は完成した。

Herokuへデプロイしてhobbyアカウントにアップグレード、SSL通信もできるようになったよ。

自分がつまずいたのは

  • post.titleではなくpost.fields.title
  • componentではasyncData ({env})は使えない
  • ContentfulのAPIには2種類ある
  • en-US
  • Oauth Appはユーザー画面から作る
  • location が undefined

あたり。

みなさんもお気をつけて〜

11
11
0

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
11
11