初夏のJavaScript祭にて発表した Gridsome のサンプルアプリ実装解説

2019年6月1日の「初夏のJavaScript祭 in メンバーズキャリア」で『Gridsome で作る JAMstack なサーバーレス Web Front』の発表をした際にデモしました Gridsome のアプリについて実装を紹介します。

今回の発表用に作ったのはGridsomeを使って、Instagramから画像をとってきて並べるだけの簡単なサンプルアプリです。実装が小さいながらも GraphQL を使い、入力ソースが簡単に扱えて、それでいて画像が出るので表現がわかりやすいかと思います。具体的な実装について聞いてくださった方がいらっしゃったので実装手順を紹介します。

今回 Instagram からの入力に使っている Gridsome の Plugin@zefman/gridsome-source-instagramは、”Currently only supports grabbing the latest photos from a user’s public instagram profile. -README.md“ とのことで、ちょっとデータを取ってこれるだけのアプリになります。ご注意ください。

発表資料で扱ったサンプルアプリの紹介スライド

環境
本記事の開発環境は以下となります。

  • Windows 10 64bit + WSL Ubuntu 18.04.1 LTS
  • Visual Studio Code
  • Node.js 12.2.0
  • Yarn 1.15.2
  • Gridsome 0.6.3
  • @zefman/gridsome-source-instagram 0.1.2

Gridsome プロジェクトの初期構築

まずは@gridsome/cliでプロジェクトの初期構築をします。今回は [project name] をsamples-gridsome-instagramとしました。

1
$ npx @gridsome/cli create [project name]

この時点でローカルサーバーを起動して、初期状態のアプリを確認できます。
下記コマンドを実行し Gridsome が起動したら、ブラウザでhttp://localhost:8080/へアクセスします。

1
2
$ cd samples-gridsome-instagram
$ yarn develop

シンプルな初期画面が表示されます。[Home] と [About] の間で高速にページの表示切替ができます。

この時点で Lighthouse(Simulated throttling (faster)) は以下のスコアを出します。(キャプチャは、GitHub Pages へデプロイして計測しています)

SEO が 91点なのは<meta name="description" />タグがないからで、プロジェクト直下/gridsome.config.jsファイルにsiteDescriptionを追加することで 100点です。サイトのタイトルはsiteNameなので、あわせて適切な名前と説明を設定します。(以下、設定項目の全文を抜粋)

1
2
3
4
5
module.exports = {
siteName: 'Gridsome',
siteDescription: 'My Gridsome project',
plugins: []
}

デフォルト値を入れていおくプルリクを出しましたが、本質的ではないのでマージされるのは難しいかな。。。

Gridsome Plugin の導入とクエリー構築

続いて@zefman/gridsome-source-instagramを導入します。
プロジェクトのディレクトリで下記コマンドを実行します。

1
$ yarn add -D @zefman/gridsome-source-instagram

/gridsome.config.jsファイルにプラグインの設定をします。(以下、設定項目の全文を抜粋)

  • usernameは、取得したいインスタグラムのユーザー名です。(現在のところタグは対応していないのでユーザー名が必要で、今回は公式のinstagramさんにしました)
  • typeNameは、GraphQL のクエリーで、このプラグインと設定を示すのに使う文字列です。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    module.exports = {
    siteName: 'Gridsome',
    siteDescription: 'My Gridsome project',
    plugins: [
    {
    use: '@zefman/gridsome-source-instagram',
    options: {
    username: 'instagram', // Instagram username
    typeName: 'InstagramPhoto' // The GraphQL type you want the photos to be added under. Defaults to InstagramPhoto
    }
    }
    ]

この状態でyarn developでローカルサーバーを再起動します。
起動したらhttp://localhost:8080/___exploreへアクセスします。
GraphQL の Playground が表示されるので、左側のクエリーエディターに以下を入力して画面中央の [▷ (再生)] ボタンをクリックします。

  • photos: allInstagramPhotoは、Plugin で指定したtypeNameの文字列allInstagramPhotophotosの名前で使うという指定です。
  • iddisplay_urlが Instagram から取得した ID と、画像の URL です。
  • textは、Instagram のコメント(一番最初のだけ)です。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    query {
    photos: allInstagramPhoto {
    edges {
    node {
    id
    display_url
    edge_media_to_caption {
    edges {
    node {
    text
    }
    }
    }
    }
    }
    }
    }

右にある [DOCS] や [SCHEMA] タブを確認しながら欲しいデータが取得できるクエリーを作っていきます。(たとえばshortcodehttps://www.instagram.com/p/[shortcode の値]でページを表示するための文字列が返ります。)

ページの作成

/src/pagesディレクトリにページ用のファイルを作ります。URL に対応するアッパーキャメルケース(パスカルケース)の文字列でファイル名 +.vueを作ります。
今回はInstagramPhotos.vueとしました。URL としては slug 化されて/instagram-photosとなります(Pages - Gridsome)。
ここからはローカルサーバーを立ち上げておきhttp://localhost:8080/instagram-photosへアクセスした状態で作業を進めます。ホットリロードでブラウザが自動更新するので確認が容易です。

コードは下記で、基本的に Vue.js です。<page-query>タグが Gridsome 特有の GraphQL のクエリーを書くための場所になります。
また画像も Gridsome 特有の<g-image>タグで、これにより最適化されます(Images - Gridsome)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<template>
<Layout>

<h1>Instagram Photos</h1>
<span v-for="edge in $page.photos.edges" :key="edge.node.id">
<a :href="'https://instagram.com/p/' + edge.node.shortcode" target="_blank" rel="noopener">
<g-image :src="edge.node.display_url" :alt="'Instagram Photo: ' + edge.node.edge_media_to_caption.edges[0].node.text" class="photo" />
</a>
</span>

</Layout>
</template>

<page-query>
query {
photos: allInstagramPhoto {
edges {
node {
id
shortcode
display_url
edge_media_to_caption {
edges {
node {
text
}
}
}
}
}
}
}
</page-query>

<style>
.photo {
width: 144px;
margin: 0 4px;
}
</style>

レイアウトにリンクを追加

ページが作れたら、そのページへアクセスするためのリンクを作ります。(以下、テンプレート部分のみ抜粋)
[Home] と [About] のリンクがあるのは/src/layouts/Default.vueです。
サイト内のページ遷移は Gridsome 特有の<g-link>タグを使います。これによりプリフェッチが効いてページ遷移を高速化できます(Linking - Gridsome)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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>
<g-link class="nav__link" to="/instagram-photos">Instagram Photos</g-link>
</nav>
</header>
<slot/>
</div>
</template>

完成!

GitHub Pages にホスティングもしました。動作している状態を確認する場合は、こちらへアクセスしてください。
(公開サイトは1つのため記事公開に合わせて変わり、本記事の内容とは異なることがあります)

また、今回作成した部分までのソースを GitHub へアップしました。

発表資料

当日の発表資料と、サマリーの記事はこちらです。
もしよかったら、ご参照ください。

Gridsome で作る JAMstack な サーバーレス Web Front』の発表資料はこちらになります。(下記、スライド埋め込み)

また発表のサマリー記事は、こちらになります。


Gridsome アプリの実装例になります。

GraphQL で簡単にデータソースの内容にアクセスできるのを感じていただけたでしょうか。このように Gridsome は Source 系 Plugin を使うことでさまざまなデータソースに容易にアクセスすることができ、GraphQL として画一的に扱うことができます。いろいろなデータソースを扱っておもしろいサイトが作れそうです。