Vuepressでブログ構築 (その1)

開発者向けの記事です。

vuepress + firebaseなら以下のような思いが実現されるはずです。

* とくかく速いページがいい!
* Markdown使いたい!
* サーバー用意とかだるい!
* 無料ではじめたい!
* 自分でレイアウトいじったり拡張したい!
* vue使いたい!
* シンプルなレイアウトが好き!

<目次>

ファイル構成

最終的にこんな感じになりました。

naritech.dev
├── package-lock.json
├── package.json
└── src
    ├── .vuepress       // VuePress関連の設定やコンポーネントを格納する
    │   ├── components  // .vueを配置
    │   ├── config.js
    │   └── public      // 画像ファイルを配置
    │ 
    ├── about           
    │   └── index.md    // Aboutページ内容
    │ 
    ├── blog            // 記事を書く(カテゴリ分け)
    │   ├── column
    │   │   └── xxx  
    │   └── tech
    │   │   └── xxx 
    │   └── index.md
    └── index.md        // Topページ

1.vuepress install

vuepressをnpmでインストール

npm install --save-dev vuepress

エラーが出る場合はnodeのバージョンを上げてみましょう

nodeの複数バージョン管理にはnが便利!

PugとScssを使いたいので以下も実行

  • SCSSを使えるようにする
npm i -D sass-loader node-sass
  • Pugを使えるようにする
npm i -D pug pug-plain-loader

2.Aboutページ作成

出来上がりはこちら

ファイル構成

    ├── .vuepress        
    │   ├── components      
    │        └── Skills.vue  // コイツ作る
    │   
    〜
    │ 
    ├── about           
    │   └── index.md         // ここいじる

SKillsコンポーネント作成

以下のようにbox系のUIのコンポーネントを.vuepress/components/に配置

<template lang="pug">
  div#skills
    div.skill-item
      span ✔︎ フロントエンド開発
    div.skill-item
      span ✔︎ サーバーサイド開発
    div.skill-item
      span ✔︎ プロダクト開発
    div.skill-item
      span ✔︎ ディレクション / PM
    div.skill-item
      span ✔︎ 教育 / メンター
    div.skill-item
      span ✔︎ イベント企画
    div.skill-item
      span ✔︎ ダンス
    div.skill-item
      span ✔︎ DJ / Mix 
</template>

<style lang="scss" scoped>
#skills {
  display: flex;
  flex-wrap: wrap;
  padding-top: 16px;
  .skill-item{
    width: 220px;
    padding: 8px;
    margin-bottom: 8px;
    border: 1px solid #ddd;
    box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
    border-radius: 5px;
    margin-right: 20px;
    text-align: center;
  }
}
</style>

呼び出しはabout/index.mdに以下のように記述します。

## Skills
<Skills/>

他の内容はmdファイルに直接記載しました。

3.Blogページ作成

出来上がりはこちら

ファイル構成

    ├── .vuepress        
    │   ├── components      
    │        └── Post.vue         // コイツ作る
    │        └── RecentPosts.vue  // コイツ作る
    │   
    〜
    │ 
    ├── blog           
    │   └── index.md             // ここいじる

Postコンポーネント作成

以下のようにPost.vueを作成しました。

noteっぽいUIを表現。

  • router-linkはSPAのためのlinkタグで、aタグにすると読み込みが遅く、router-linkだと初期読み込みがされて高速に遷移できます。
  • $withBaseは環境に合わせた絶対パスを返す関数のようです。
  • titleをホバーしたらアンダーラインがビヨーン!と伸びるようにしました。(.link部分)
<template lang="pug">
div.post
    section.inner
        router-link(:to="'/blog/' + id + '/'")
            img(:src="$withBase(thumbnail)", width="500")
        div
            h3.title
                router-link.link(:to="'/blog/' + id + '/'") {{ title }}
            p.description {{ description }}
            span.date {{ date }}
</template>

<script>
export default {
    props: {
        id: String,
        thumbnail: String,
        title: String,
        description: String,
        date: String
    }
}
</script>

<style lang="scss" scoped>
.post {
    padding-bottom: 40px;
    margin-bottom: 40px;
    border-bottom: 1px solid #e6e6e6;
    .inner {
      padding: 16px;
      img {
        &:hover {
            cursor: pointer;
        } 
      }
      .title {
        margin-bottom: 8px;
        font-weight: 700;
        line-height: 1.5;
        letter-spacing: 0.04em;
        word-break: break-all;
        -webkit-font-feature-settings: "palt" 1;
        font-feature-settings: "palt" 1;
        font-size: 22px;
        .link {
          position: relative;
          display: inline-block;
          text-decoration: none;
          &:after {
            position: absolute;
            bottom: -4px;
            left: 0;
            content: "";
            width: 100%;
            height: 2px;
            background: #46bd87;
            transform: scale(0, 1);
            transform-origin: left top;
            transition: transform 0.3s;
          }
          &:hover::after {
            transform: scale(1, 1);
          }
        }
      }
      .description {
        font-size: 14px;
        color: #2c3e50;
      }
      .date {
        font-size: 12px;
        display: block;
        line-height: 1.5;
        color: #787c7b;
      }
    }
  }
</style>

RecentPostsコンポーネント作成

posts配列に記事情報を入れてループしてPostコンポーネントに渡します。
コードがスッキリしていいですね!
新しい記事を追加したら手作業で配列に追加するのは少し手前ですが一旦この仕様でいいでしょう。
最初からいろいろ便利にしようとすると実装が大変なので、ベタでも早く実装できる方法を取りました。

<template lang="pug">
div.posts
  post(v-for="(item, index) in posts" :id="item.id" :thumbnail="item.thumbnail" :title="item.title" :description="item.description" :date="item.date")
</template>

<script>
export default {
    props: {
      //
    },
    data() {
      return {
        posts: [
          { id: 'column/1', title: 'サイトオープン!', thumbnail: '/blog_1_top.jpg', description: 'このサイトを立ち上げたよーってはなし(Column)', date: '2019/06/15'}
          ]
      }
    },
    methods: {
      //
    }
}
</script>

4.Topページ修正

index.mdの作成

src以下にindex.mdファイルを作成します。

Title, Descriptionなどを指定する

index.mdを以下のようにします。

---
home: true
heroImage: /top_icon.jpg
heroText: NARI TECH
tagline: Make Your Life Happy With Creative
actionText: About →
actionLink: /about/
footer: © 2019 NARI TECH.
---
  • home: true → ホーム画面だよって明示
  • heroImage: xxxx → Topのイメージパス(public以下に画像を入れる)
  • heroText: xxxx → Topのヘッダーテキスト
  • tagline: xxxx → ヘッダー下のdescriptionテキスト
  • actionText: xxxx → アクションボタンのテキスト
  • actionLink: xxxx → アクションボタンのリンク先
  • footer: xxxx → フッターのテキスト

レイアウト調整

Topの画像を丸くしたかったのでsrc/.vuepress/override.stylを作成し、上書き用のstyleを追加しました。

.home {
  .hero {
    img {
      border-radius: 50%;
    }
  }
}

RecentPostsの配置

components以下のコンポーネントはどこでも使えるので以下のよう記述。

## Blog
<RecentPosts/>

Linksコンポーネント作成

以下のように各サイトのテーマカラーを使ったボタン型リンクを作成しました。

<template lang="pug">
    div#links
       a#twitter.item.text(target="_blank",href="https://twitter.com/NARI_Creator") Twitter
       a#github.item.text(target="_blank",href="https://github.com/narith-minami") GitHub
       a#menta.item.text(target="_blank",href="https://menta.work/user/302") MENTA
       a#note.item.text(target="_blank",href="https://note.mu/narith") note
       a#qiita.item.text(target="_blank",href="https://qiita.com/NARI_Creator") Qiita
</template>

<script>
export default {
    props: []
}
</script>

<style lang="scss" scoped>
#links{
  display: flex;
  flex-wrap: wrap;
  padding-top: 16px;
  padding-bottom: 32px;
  .item{
    text-decoration: none;
    color: #fff;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    margin-right: 12px;
    margin-bottom: 12px;
    width: 80px;
    height: 80px;
    display: flex;
    box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
    border-radius: 50%;
    &:hover{
      opacity: 0.8;
      box-shadow: 2px 2px 5px rgba(0,0,0,0.4);
      top: -1px;
      position: relative;
      transition-property: all;
      transition: 0.3s linear;
    }
    .text {
      margin:auto;
      color: #fff;
    }
  }
  #twitter{
     background-color: #55acee;
  }
  #github{
    background-color: #4183c4;
  }  
  #note{
    background-color: #2cb696;
  }
  #qiita{
    background-color: #55c500;
  }
  #menta{
    background-color: #13b1c0;
  }
}
</style>

▼index.md全体

---
home: true
heroImage: /top_icon.jpg
heroText: NARI TECH
tagline: Make Your Life Happy With Creative
actionText: About →
actionLink: /about/
footer: © 2019 NARI TECH.
---
## Blog
<RecentPosts/>


## Service
### TEAMKIT
TEAMKITはフリーランス同士、クリエイター同士がお互いにプロジェクトをシェアすることが出来るプラットフォームです。クライアントから相談受けたけど、ひとりで回せないとか一緒に組めるクリエイターを探してるといったことを解決できることを目指しています。

<a href="https://teamkit.jp/" target="_blank"><img :src="$withBase('/teamkit_intro.png')" alt="TEAMKIT"></a>
<a href="https://teamkit.jp/" target="_blank">https://teamkit.jp/</a>

## Link
<Links/>

5.Navigationの設定

src/.vuepress/config.jsを以下のように修正して「Home, About, Blog」を表示するようにしました。

module.exports = {
    title: 'NARI TECH',
    description: 'Make Your Life Happy With Creative',
    themeConfig: {
        nav: [
          { text: 'Home', link: '/' },
          { text: 'About', link: '/about/' },
          { text: 'Blog', link: '/blog/' }
        ]
      }
}

出来上がりはこちら

6.npm run buildでstaticファイル作成

ここまで実装してlocalhostで動作検証ができたら後はstaticファイル(静的ファイル)を作成して、ホスティング先にアップします。

以下のコマンドを実行して成功することを確認して次へ

npm run build

7.firebase HostingにDepoy

netlify,S3など静的ホスティングサービスはいろいろありますが、無料で高速に動く環境のfirebaseにしました。(他のサービスでもなんでもいいのでここはお好みで)

こちらの記事が分かりやすいです

デプロイが正常にでき無事に公開!

いろいろ調べたりコンポーネント作ったりしたので2,3日かかりましたが、ググって見つかるチュートリアルを見てデフォルトテーマで動かすだけなら1時間かからず終わると思います。

ぜひあなたもトライ!

今後の拡張もここのブログでつらつら書いていきますのでよろしくです!