Gridsomeを利用して簡単なサイトを作成しよう
静的ジェネレータであるGridsomeの調査として簡易的なサイトの構築を試してみたいと思います。ローンチ直後に比べてプラグインなども揃ってきていてブログやHPであれば十分構築できると思います。今後の開発でGridsomeが導入できるように基礎知識をつけていきたいと思います。
[ 目次 ]
はじめに
こんにちは、香港に住んでいるWEBデベロッパーのなかむ(@nakanakamu0828)です。
今回は、静的ジェネレータであるGridsomeを試していきたいと思います。
【内容】
- Gridsomeの入門としてGetting started に沿って開発環境を構築する
- プラグインを導入し、UIの変更(Tailwind CSSを利用)や投稿機能の追加を行う
- 成果物をNetlifyにデプロイする
【対象者】
- Gridsomeを利用してホームページやコーポレートサイト、ブログを構築したいGridsome初学者。または、フロントエンドを学んでいきたいバックエンドエンジニア
【注意事項】
- 進めていく前提として
npm
,yarn
がインストールされていることを想定しています。 - 本投稿でTailwind CSSのプラグインを導入していきます。Tailwind CSS導入後はTailwind CSSでUIを構築しています。
- Netlifyの新規登録や利用方法については述べません。デプロイ部分のみになります。
Gridsomeとは
GatsbyJSにインスパイアされたVue.jsでUI部分を実装できる静的サイトジェネレーターです。
特徴については公式サイトをご確認ください。
Gridsome入門
Gridsomeの公式サイト - Getting started を参考に進めていきます。
インストール
■ npmを利用する場合
$ npm install --global @gridsome/cli
■ yarnを利用する場合
$ yarn global add @gridsome/cli
プロジェクト作成
$ gridsome create gridsome-site-starter
$ cd gridsome-site-starter
$ gridsome develop
http://localhost:8080/ でブラウザからアクセスできれば成功です。
以下の初期画面が表示されることを確認してください。
ページを追加する
既に、トップページとAboutページが用意されています。
今回はTerm(規約)ページを追加して見ましょう。
$ # gridsome-site-starterディレクトリ配下にいる想定です。
$ touch src/pages/Term.vue
Term.vue
の内容は以下のような内容にします。
<template>
<Layout>
<h1>Term</h1>
<p>利用規約・・・・</p>
</Layout>
</template>
<script>
export default {
metaInfo: {
title: 'Term'
}
}
</script>
ヘッダーにTerm
のリンクを追加します。
src/layouts/Default.vue
のtemplate内を変更しましょう。
<template>
<div class="layout">
<header class="header">
<strong>
<g-link to="/">{{ $static.metaData.siteName }}</g-link>
</strong>
<nav class="nav">
<g-link class="nav__link" to="/">Home</g-link>
<g-link class="nav__link" to="/about">About</g-link>
<!-- この1行を追加 -->
<g-link class="nav__link" to="/term">Term</g-link>
<!-- ここまで -->
</nav>
</header>
<slot/>
</div>
</template>
ここまでの修正によりヘッダーで画面遷移することができるようになります。
Gridsomeのプラグインを利用する
公式サイト - PLUGINS にプラグインが用意されています。今回はその中から何個かピックアップして導入してみます。
gridsome-plugin-tailwindcss
gridsome-plugin-tailwindcss
は、私のブログでも何度か取り上げてきた Tailwind CSS を組み込む為のプラグインです。
過去のブログ記事は以下からご確認ください。
それではgridsome-plugin-tailwindcss
をインストールしていきましょう。
以下のコマンドからプラグインをインストールします。
■ npmを利用する場合
$ npm install --save-dev gridsome-plugin-tailwindcss
■ yarnを利用する場合
$ yarn add --dev gridsome-plugin-tailwindcss
続けて Tailwind CSSの初期化 を行います。
■ npmを利用する場合
$ npm tailwind init [filename]
■ yarnを利用する場合
$ yarn tailwind init [filename]
今回はfilename
をsrc/tailwind.js
とし、gridsomeのsrc
ディレクトリ直下にtailwind.js
を配置しました。
続いてエントリーポイントになるCSSファイルを作成します。Tailwind CSSのUse Tailwind in your CSSの部分です。
$ mkdir -p src/assets/
$ touch src/assets/tailwind.css
内容は以下のようなtailwindの読み込みを記述します。
@tailwind preflight;
@tailwind components;
@tailwind utilities;
作成したtailwind.css
は、src/main.js
にてimportしましょう。
import '~/assets/tailwind.css'
最後に、gridsome-plugin-tailwindcss
プラグインの読み込み設定を追加します。
gridsome.config.js
を以下のように修正しましょう。
module.exports = {
siteName: 'Gridsome',
plugins: [
{
use: 'gridsome-plugin-tailwindcss',
options: {
config: './src/tailwind.js'
}
}
]
}
これでTailwind CSSが読み込まれるようになります。gridsome develop
を再度起動して確認しましょう。
(ここではTailwind CSSを利用したHTMLコーディングは省略します)
gridsome-plugin-purgecss
Tailwind CSSの未使用のclassをbuild時に除外し、cssのファイルサイズを圧縮したい場合にpurgecss
が利用できます。
今回は、gridsome-plugin-purgecss
プラグインを利用してpurge
を行います。
purgecss
についてや導入については過去のブログ記事もご確認ください。
Laravel & Tailwind CSS のプロジェクトにPurgecssを導入する
それではgridsome-plugin-purgecss
をインストールしていきましょう。
以下のコマンドからプラグインをインストールします。
■ npmを利用する場合
$ npm install --save-dev gridsome-plugin-purgecss
■ yarnを利用する場合
$ yarn add --dev gridsome-plugin-purgecss
続いて、gridsome.config.js
にpurgecss
の設定を追加していきます。
以下のように修正しましょう。
class TailwindExtractor {
static extract(content) {
return content.match(/[A-z0-9-:\/]+/g) || []
}
}
module.exports = {
siteName: 'Gridsome',
plugins: [
{
use: 'gridsome-plugin-tailwindcss',
options: {
config: './src/tailwind.js'
}
},
{
use: 'gridsome-plugin-purgecss',
options: {
content: [
'./src/**/*.vue',
'./src/**/*.js',
'./src/**/*.jsx',
'./src/**/*.md'
],
extractor: TailwindExtractor,
extensions: ['vue', 'js', 'jsx', 'md']
}
}
]
}
ファイルサイズが圧縮されたかどうかは、gridsome build
でdist
配下にbuildした静的ファイルを生成し確認できます。Tailwind CSSでUIを構築した後、purgecss
の有無でjs, cssのファイルサイズを確認してみましょう。
@gridsome/source-filesystem
投稿データをmarkdownファイルで管理できるように@gridsome/source-filesystem
プラグインを導入します。markdownを利用するので@gridsome/transformer-remark
プラグインを一緒にインストールしましょう。
以下のコマンドからプラグインをインストールします。
■ npmを利用する場合
$ npm install --save-dev @gridsome/source-filesystem @gridsome/transformer-remark
■ yarnを利用する場合
$ yarn add --dev @gridsome/source-filesystem @gridsome/transformer-remark
続いて、gridsome.config.js
に@gridsome/source-filesystem
の設定を追加し、ブログ投稿ページのルーティング設定やファイルの配置場所、UIテンプレートとして利用するVueファイルを定義します。
以下のように修正しましょう。
module.exports = {
siteName: 'Gridsome',
plugins: [
・・・
{
use: '@gridsome/source-filesystem',
options: {
// 投稿ファイルは、blogディレクトリ配下に配置
path: 'blog/*.md',
// 投稿ページのUIテンプレートは、BlogPost.vueとします
typeName: 'BlogPost',
// URLパスは、/blog/:slagとしてアクセス可能
route: '/blog/:slug'
}
},
・・・
],
transformers: {
remark: {
// 外部リンクは target="_blank"になるように設定
externalLinksTarget: '_blank',
// SEO対策として外部リンクは rel="nofollow noopener noreferrer"になるように設定
externalLinksRel: ['nofollow', 'noopener', 'noreferrer'],
plugins: [
]
}
}
}
次にブログ投稿ページのUIテンプレートを作成しましょう。
公式サイト - Templates を参考に進めていきます。
以下のコマンドからsrc/templates/BlogPost.vue
を作成してください。
BlogPost
という名称はgridsome.config.js
のtypeName
と一致するようにします。
$ touch src/templates/BlogPost.vue
src/templates/BlogPost.vue
は以下のように実装します。
<template>
<Layout>
<div class="container mx-auto sm:py-10 flex justify-center">
<div class="max-w-lg rounded overflow-hidden shadow-lg">
<div class="px-6 py-4 border-b mb-2">
<p class="my-1 text-sm text-grey-darker">
<span class="text-grey-darker text-sm">
{{ $page.blogPost.createdAt }}
<svg class="h-3 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1792 1792" fill="currentColor"><path d="M1639 1056q0 5-1 7-64 268-268 434.5t-478 166.5q-146 0-282.5-55t-243.5-157l-129 129q-19 19-45 19t-45-19-19-45v-448q0-26 19-45t45-19h448q26 0 45 19t19 45-19 45l-137 137q71 66 161 102t187 36q134 0 250-65t186-179q11-17 53-117 8-23 30-23h192q13 0 22.5 9.5t9.5 22.5zm25-800v448q0 26-19 45t-45 19h-448q-26 0-45-19t-19-45 19-45l138-138q-148-137-349-137-134 0-250 65t-186 179q-11 17-53 117-8 23-30 23h-199q-13 0-22.5-9.5t-9.5-22.5v-7q65-268 270-434.5t480-166.5q146 0 284 55.5t245 156.5l130-129q19-19 45-19t45 19 19 45z"></path></svg>
{{ $page.blogPost.updatedAt }}
</span>
</p>
<h1 class="my-2">{{ $page.blogPost.title }}</h1>
<p class="my-2 text-sm text-grey-darker">{{ $page.blogPost.description }}</p>
<div class="my-1">
<span
class="inline-block bg-grey-lighter rounded-full px-3 py-1 text-sm font-semibold text-grey-darker mr-2"
v-for="tag in tags"
:key="tag"
v-text="`#${tag}`"
/>
</div>
<g-image class="mt-5" :src="$page.blogPost.image"/>
</div>
<div class="px-6 py-4 content" v-html="$page.blogPost.content" />
</div>
</div>
</Layout>
</template>
<script>
export default {
metaInfo () {
return {
title: this.$page.blogPost.title
}
},
computed: {
tags () {
return this.$page.blogPost.tags.split(' ');
},
totalCount () {
return this.$page.allPost.totalCount
}
},
}
</script>
<page-query>
query BlogPost ($path: String!) {
blogPost (path: $path) {
title
description
createdAt (format: "YYYY.MM.D")
updatedAt (format: "YYYY.MM.D")
content
image
tags
}
}
</page-query>
<style>
.content {
@apply text-base;
}
.content > h1 {
font-size: 1.5rem;
@apply py-2;
}
.content > p {
@apply text-grey-darker mb-2;
}
</style>
Home画面にブログの一覧を表示します。Home画面からブログ投稿ページに遷移できるようにしましょう。
src/pages/Indev.vue
の内容を以下のように変更します。
<template>
<Layout>
<div class="container mx-auto p-10 flex justify-center">
<div class="max-w-lg">
<div
class="w-full lg:flex"
v-for="{ node } in $page.allBlogPost.edges"
:key="node._id"
>
<div class="border border-grey-light bg-white rounded p-4 flex flex-col justify-between leading-normal">
<p class="my-1 text-sm text-grey-darker">
<span class="text-grey-darker text-sm">
{{ node.createdAt }}
<svg class="h-3 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1792 1792" fill="currentColor"><path d="M1639 1056q0 5-1 7-64 268-268 434.5t-478 166.5q-146 0-282.5-55t-243.5-157l-129 129q-19 19-45 19t-45-19-19-45v-448q0-26 19-45t45-19h448q26 0 45 19t19 45-19 45l-137 137q71 66 161 102t187 36q134 0 250-65t186-179q11-17 53-117 8-23 30-23h192q13 0 22.5 9.5t9.5 22.5zm25-800v448q0 26-19 45t-45 19h-448q-26 0-45-19t-19-45 19-45l138-138q-148-137-349-137-134 0-250 65t-186 179q-11 17-53 117-8 23-30 23h-199q-13 0-22.5-9.5t-9.5-22.5v-7q65-268 270-434.5t480-166.5q146 0 284 55.5t245 156.5l130-129q19-19 45-19t45 19 19 45z"></path></svg>
{{ node.updatedAt }}
</span>
</p>
<router-link
:to="node.path"
class="no-underline text-black font-bold text-xl py-1"
>
<h3 v-html="node.title"/>
</router-link>
<p class="text-grey-darker text-base mb-2"
v-html="node.description"
/>
<div class="my-1">
<span
class="inline-block bg-grey-lighter rounded-full px-3 py-1 text-sm font-semibold text-grey-darker mr-2"
v-for="tag in node.tags.split(' ')"
:key="tag"
v-text="`#${tag}`"
/>
</div>
</div>
</div>
</div>
</div>
</Layout>
</template>
<script>
export default {
metaInfo: {
title: 'Home'
}
}
</script>
<page-query>
query Home ($page: Int) {
allBlogPost (page: $page) {
edges {
node {
_id
title
createdAt (format: "YYYY.MM.D")
updatedAt (format: "YYYY.MM.D")
description
path
tags
}
}
}
}
</page-query>
最後にblog
ディレクトリ配下に投稿用のmarkdownファイルを作成しましょう。
$ mkdir -p blog
$ # 画像の配置場所も用意
$ mkdir -p blog/images
$ touch blog/`date +'%Y-%m-%d'`_first_blog.md
投稿ファイルは以下のような内容にします。
画像を作成し設定していることに注意してください。
---
title: ブログ初投稿です。
createdAt: 2019-03-04 00:00:00
updatedAt: 2019-03-04 00:00:00
description: "初めてのブログ投稿です。初めてのブログ投稿です。初めてのブログ投稿です。初めてのブログ投稿です。初めてのブログ投稿です。初めてのブログ投稿です。"
image: "./images/gridsome_starter_blog_image1.png"
slug: first-post
tags: aaa bbb ccc
---
# ブログを初めて投稿1
テストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテスト。
[Google](https://www.google.co.jp/)
# ブログを初めて投稿2
テストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテスト。
[Yahoo](https://www.yahoo.co.jp/)
# ブログを初めて投稿3
テストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテスト。
# ブログを初めて投稿4
テストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテスト。
# ブログを初めて投稿5
テストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテストテスト。
ここまで作成できると以下のようにHome画面の一覧から投稿画面への遷移ができるようになります。
@gridsome/remark-prismjs
@gridsome/remark-prismjs
プラグインを導入することで、Prismのコードハイライトが実現できます。こちらも導入してみましょう。
以下のコマンドからプラグインをインストールします。
■ npmを利用する場合
$ npm install --save-dev @gridsome/remark-prismjs
■ yarnを利用する場合
$ yarn add --dev @gridsome/remark-prismjs
続いてgridsome.config.js
に@gridsome/remark-prismjs
の設定を追加します。
@gridsome/source-filesystem
のremark
プラグインとして@gridsome/remark-prismjs
を追加する形になります。
以下のようにgridsome.config.js
を修正しましょう。
module.exports = {
siteName: 'Gridsome',
plugins: [
・・・
{
use: '@gridsome/source-filesystem',
options: {
// 投稿ファイルは、blogディレクトリ配下に配置
path: 'blog/*.md',
// 投稿ページのUIテンプレートは、BlogPost.vueとします
typeName: 'BlogPost',
// URLパスは、/blog/:slagとしてアクセス可能
route: '/blog/:slug',
// 以下を追加 - この設定の場合投稿ページにてprismjsが適応されます
remark: {
plugins: [
'@gridsome/remark-prismjs'
]
}
// ここまで
}
},
・・・
],
・・・
}
このままだとスタイルが適応されません。
@gridsome/remark-prismjs
インストール時にテーマもインストールされています。今回は prismjs/themes/prism-okaidia.css
を利用します。
src/main.js
にimportしましょう。
import 'prismjs/themes/prism-okaidia.css'
他にもprism-themesからテーマを選べます。自分が好きなテーマを組み込みましょう。
注意事項)
purgecssを導入している場合、prismテーマのcssがパージされてしまいます。gridsome.config.js
内にあるgridsome-plugin-purgecss
の設定を以下のように変更してください。
module.exports = {
siteName: 'Gridsome',
plugins: [
・・・
{
use: 'gridsome-plugin-purgecss',
options: {
content: [
'./src/**/*.vue',
'./src/**/*.js',
'./src/**/*.jsx',
'./src/**/*.md',
// 以下の1行を追加
'node_modules/prismjs/**/*.js'
// ここまで
],
extractor: TailwindExtractor,
extensions: ['vue', 'js', 'jsx', 'md']
}
}
]
}
この設定をすることでprismjsのjavascriptから利用されているclassを検索しパージ対象外とします。
@gridsome/plugin-sitemap
サイトマップを生成するプラグインです。こちらも導入してみましょう。
以下のコマンドからプラグインをインストールします。
■ npmを利用する場合
$ npm install --save-dev @gridsome/plugin-sitemap
■ yarnを利用する場合
$ yarn add --dev @gridsome/plugin-sitemap
続いて、gridsome.config.js
にplugin-sitemap
の設定を追加していきます。
以下のように修正しましょう。
configにsiteUrl
を追加し、サイトのベースURLを設定しましょう。
module.exports = {
siteName: 'Gridsome',
siteUrl: 'https://gridsome-starter-site.netlify.com', // サイトのベースURLを設定
plugins: [
・・・
{
use: '@gridsome/plugin-sitemap',
options: {
cacheTime: 600000,
exclude: ['/exclude-me'],
config: {
'/blog/*': {
changefreq: 'weekly',
priority: 0.5
},
'/about': {
changefreq: 'monthly',
priority: 0.7
},
'/term': {
changefreq: 'monthly',
priority: 0.7
}
}
}
}
・・・
]
}
サイトマップの生成については、gridsome build
でbuildを行うとdist/sitemap.xml
が作成されるので、そちらから確認が可能になります。
Google Fontsの導入
Google Fonts のページから利用したいフォントのURLをコピーします。
src/main.js
にheadタグのlinkにGoogle FontsのURLを追加すれば読み込みが完了です。
export default function (Vue, { head }) {
head.link.push({
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css?family=Roboto'
})
}
後は、classで指定したフォントを定義し、html内のclass属性に設定すればフォントが反映されます。
Netlifyへのデプロイ
作成したGridsomeのサイトをNetlifyにデプロイします。githubと連携してNetlifyにデプロイしてみましょう。
netlify.tomlの作成
netlify.toml
にデプロイ時のbuild設定を記述します。
[build]
publish = "dist"
command = "yarn build"
githubにpush
github上でリポジトリを作成しpushしてください。
私のリポジトリの場合、以下のようなコマンドでpushまで行いました。
git remote add origin git@github.com:nakanakamu0828/gridsome-starter-site.git
git push -u origin master
※ 各環境に合わせてgithubのURLは変更してください。
Netlifyの管理画面からgithubと連携してデプロイ
Netlifyのダッシュボードから"New site from Git"ボタンを押下し、デプロイするgithubリポジトリを選択することでデプロイが開始されます。
成果物
以下が今回作成したGridsomeのリポジトリになります。
ソースの詳細はこちらをご確認ください。
出来上がったサイトはこちらです。
簡易的なサイトですが、ChromeでLighthouseを測定してみるとかなり結果がよかったです。"Progressive Web App"の点数が低いですが、gridsomeのPWA機能が待ち遠しいところです。
最後に
今回はGridsomeを試してきました。静的サイトの構築であればNuxt.jsを利用するよりGridsomeの方が簡単に導入できるのではないでしょうか?
- HedressCMSを利用した投稿データの連携
- 投稿ページのページング
- -タグやカテゴリの管理とタグページ、カテゴリーページの作成
は行っていません。引き続き実装方法を調査したいと思います。