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時間かからず終わると思います。
ぜひあなたもトライ!
今後の拡張もここのブログでつらつら書いていきますのでよろしくです!