Gatsby.jsでサイト作成
Gatsby.jsを使ってstaticなサイトを作成する
October 27, 2018
柏市議会の議事録を解析して、各会議ごとに重要な単語を抜き出して結果を公開しました。
https://council-kashiwa.netlify.com/
重要=TFIDFが大きい、と定義しています。 TDIDFの詳細はググってもらえれば良いとして、ざっくり言えば特定の会議で頻繁に発言される単語は重要だろう、という考え方に従った指標です。 結果を見ると結構面白く、その時々にどんなことが社会的に話題になっていたかある程度把握できるくらいに特徴がつかめています。 ただ、本記事の主題はその解析結果ではなく、サイトを作るにあたって利用したGatsby.jsが主題です。
Gatsby.js
一言で言えば、静的サイトジェネレータです。
レイアウトやページテンプレートの定義にReactを使っている、webpackによるビルド環境のセットアップをGatsby.jsがやってくれる、などの特徴があります。 ただ、これだけだとcreate-react-appを使うのとそんなに変わらないです(もちろんRoutingやレイアウト機能など、create-react-app よりもGatsby.jsでやってくれることは多いです)。 Gatsby.jsで最も特徴的な機能は、サイト生成に必要なデータを集めるためのpluginシステムと、そのデータ取得ためのクエリとしてGraphQLを使っていることだと私は考えます。
データソース
Gatsby.jsでは、サイト生成に必要となるデータはGraphQLを使って取得します。 一番シンプルな例は Tutorialのpart4 を見ていただくと早いです。 Tutorialでは、configに設定されたサイト名をGraphQLを使って取得してh1タグでページに埋め込んでいます。
GraphQLで取得可能なデータはpluginを使って拡張可能です。
Tutorialのpart5にその説明があります。
そこでは、ローカルのfilesystemをデータソースとして利用しています。
plugin検索ページで source
と検索してみると、実に多様なデータソースに対応していることがわかります。Tutorialで使われているfilesystemに限らず、twitterなどのwebサービス、あるいはwordpressなどのcmsをデータソースとすることも可能なようです。
Markdownファイルからブログサイトを作ったり、商品DBからECサイトを作る、といった例が考えられます。
gatsby-source-apiserver
今回私は、gatsby-source-apiserver
という、任意のAPIをデータソースにするpluginを利用しました。
冒頭に紹介した議事録のTFIDF解析結果は、jsonで取得できるようにしてあります。
ページ読み込み後にjsonをfetchして描画するのではなく、サイトの生成時に取得してhtml内に埋め込みます。
以下は私の設定です。gatsby-config.jsのpluginsの配列に追加します。
{
resolve: 'gatsby-source-apiserver',
options: {
// GraphQLで参照する際のprefix
// 後ろに__がついていますが、GraphQL上で表示されるスキーマ名にはinternalしかついていませんでした。
typePrefix: 'internal__',
// 取得先のURL
// ビルド時に環境変数を利用可能です。
url: `${process.env.API_ENDPOINT}/council/tfidf.json`,
// HTTPメソッド
method: 'get',
// 取得リクエストのヘッダー
headers: {
'Content-Type': 'application/json'
},
// データ名
// prefixと結合した結果で参照することになります。
name: `tfidfs`,
// とりあえず空
// レスポンスがネストしているときに使う?
entityLevel: ``,
verboseOutput: true, // For debugging purposes
},
}
tfidf.jsonでは以下のようなレスポンスを返します。
{
tfidfs: [
{
dateKey: '11_09_03',
words: [
{ word: '陳情', score: 0.3438... },
...
],
},
...
]
}
GraphQLで必要となるSchemaはGatsby.jsの方で推測してくれるようです 1。データを利用するときは、
...
import { graphql } from 'gatsby';
...
const IndexPage = ({data}) => {
return (
<Layout>
...
<div>
{data.internalTfidfs.tfidfs.map((tfidf) => { ... }}
</div>
</Layout>
);
};
export defaul IndexPage;
export const query = graphql`
query {
internalTfidfs {
tfidfs {
dateKey
words {
word
}
}
}
}
`;
とします。query
で必要な情報をGraphQLで定義し、コンポーネント内で取得した値を利用します。
APIはTFIDFの値をscoreで返していますが、画面では不要なのでGraphQLのクエリ上ではwordのみ取得します。
deploy
gatsby build
すると public
フォルダが生成されるので、それをs3などにアップしてください。
netflifyを使うと、buildからデプロイまでnetlify上で完結するので楽です。