ポートフォリオ
Hugo
postcss
Netlify

HUGO + PostCSS + Netlifyでポートフォリオサイトを作った話


はじめに

静的サイトジェネレーターのHUGO、Node.js製のCSSフレームワークであるPostCSS、ビルド + ホスティングサービスのNetlifyを使ってポートフォリオを作ったので、作り方を公開したいなと思い、作成しました。

https://shinya-sato.com/

shinya-sato.com_.png

今回は 「どうやって作ったか」 について書いているので、ポートフォリオの構成とかについては原則書かない事にしておきます。


HUGO

HUGOとは、Go言語製の静的サイトジェネレーターです。

「シンプルだが多機能」という特徴があります。

生のhtmlをそのまま編集するのと同じ要領で、「関連記事の表示」「多言語対応」等の高等な機能も持ち合わせています。


何故HUGOを選んだのか

結論からいうと、 参考にしたポートフォリオサイトがHUGOで実装されていたからです。

Jekyllはbuildが遅いし、カスタム投稿のページネーションは実装できないなど、痒いところに手が届かなかったので、他の静的サイトジェネレーターを探していました。

StaticGenを見たら、GithubのStar数も多いので使ってみました。


HUGOをインストールする

まずはhomebrewを使って、HUGOをインストールします。

brew install hugo


Repositoryをcloneする

さっそく作り始める、のではなく、 参考にするRepositoryをcloneするところから 始めます。

そして、 技術を徹底的にパクリまくります。


HUGOでサイトを作り始める

ある程度技術を盗んだら、早速HUGOでサイトを作り始めます。

hugo new site directory_name

Congratulations! Your new Hugo site is created in /Users/cookboys/documents/directory_name.

Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
Choose a theme from https://themes.gohugo.io/, or
create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
with "hugo new <SECTIONNAME>/<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.


HUGOを立ち上げてみる

コマンドを叩いたら、HUGOのサイトが出来ていると思いますので、ディレクトりに移動します。

cd directory_name

ディレクトりに移動したら、コマンドを叩いて、HUGOを立ち上げてみたいと思います。

hugo server -w

hugo-start.png

何も表示されていません(Jekyllと違って、サンプル画面すらありません)

HUGOは必要最小限の動作環境だけ提供されるので、ここから自分で環境を構築していきます。


PostCSSを導入する

必要最小限の環境しかありませんので、AltCSSの環境も自分で用意する必要があります。

なので今回は、Node.js製のCSSフレームワークである、PostCSSを導入してみたいと思います。


なぜPostCSSなのか

単刀直入に言うと、


  • Sassに飽きたから

  • トランスパイルが早いから

  • 実績ある企業が採用しているから(Facebook, Github, Qiita, Taobao等)


そもそもPostCSSって何?

PostCSSとは、先ほど申した通り、Node.js製のCSSフレームワークです。

Node.js製といえば、StylusというCSSプリプロセッサーがありますが、PostCSSはStylusと違い、インストールしただけでは何もしれくれません!

「CSSフレームワーク」の名の通り、PostCSSはプラグインを追加して、自分独自のCSSプリプロセッサーを作るツールなのです。

なので、プラグインを追加しないと、何もしれくれません。


  • Stylusの場合

    stylus.png

    Node.jsが、.styl形式で書かれたファイルを、CSSに変換する。


  • Sassの場合

    sass.png

    Rubyが、.sass形式で書かれたファイルを、CSSに変換する。


  • PostCSSの場合

    postcss.png

    Node.jsが、ファイルをCSSに変換するのはStylusと同じですが、拡張子が.cssのままです。

    当然ですが、このままでは使えるCSSになりません。

    @reset-global pc;も、@custom-media --smartphone(width <= 600px);も、CSSの構文には存在しないからです。

    これらを使えるようにするには、PostCSSのプラグインを追加しないといけません。



PostCSSを使えるようにする

では実際に、PostCSSを使えるようにしていきたいと思います。


npmを導入する

HUGOのディレクトリで、以下のコマンドを実行して、npmを導入します。

npm init


yarnをインストールする

以下のコマンドを実行して、yarnをインストールします。

npm install -g yarn


PostCSSをインストールする

以下のコマンドを実行して、PostCSSをインストールします。

yarn add postcss


CLIをインストールする

以下のコマンドを実行して、postcss-cliをインストールします。

yarn add postcss-cli


CLIの設定をする

CLIを使うために、設定ファイルの作成と、スクリプトを設定します。


  • postcss.config.js

module.exports = (ctx) => ({

plugins: []
});


  • package.json

{

"scripts": {
"start": "hugo server -w & postcss postcss/*.css -d static/assets/styles/ -w",
"build": "hugo & postcss postcss/*.css -d docs/assets/styles/"
},
"dependencies": {
"postcss": "^6.0.19",
"postcss-cli": "^5.0.0"
}
}

HUGOを実行するスクリプトと、PostCSSを実行するスクリプトを一緒にしました。

これで、yarn startを実行すると、HUGOとPostCSSが同時に起動します。


PostCSSのプラグインをインストールする

さて、準備ができましたので、この画像のCSSを使えるようにするために、PostCSSのプラグインをインストールします。

postcss02.png

yarn add postcss-css-reset postcss-mixins postcss-simple-vars postcss-color-function postcss-nested postcss-custom-media postcss-media-minmax 



  • postcss-css-reset


    • PostCSSでreset.cssを設定できる。




  • postcss-mixins


    • Postcssでmixinsを設定できる。




  • postcss-simple-vars



    • $を使った変数を使うことができる。




  • postcss-color-function


    • color変数を使うことができる。




  • postcss-nested


    • PostCSSでNest(入れ子)を使うことができる。




  • postcss-custom-media



    • @mediaに名前をつけてコンポーネント化することができる。




  • postcss-media-minmax



    • @mediaを不等号で指定できる。




configファイルに設定を記載する

プラグインを追加しただけではまだダメなので、postcss.config.jsに設定を記載します。

module.exports = (ctx) => ({

plugins: [
require('postcss-css-reset'),
require('postcss-mixins'),
require('postcss-simple-vars'),
require('postcss-color-function'),
require('postcss-nested'),
require('postcss-custom-media'),
require('postcss-media-minmax')
]
});

この順番通りにプラグインが読み込まれるので、順番は非常に重要です。


HUGOで条件分岐をする

PostCSSの設定が終わったので、HUGOに戻ります。


トップページのタイトルを変える

トップページはタイトルを変えたいので、条件分岐を設定していきます。

<title>{{if .IsHome}}{{ .Site.Params.homeTitle }}{{ else }}{{ .Title }}{{ end }} | {{ .Site.Params.SiteName }}</title>

これで、トップページの際はconfig.tomlで設定した、homeTitleが呼び出されて、それ以外のページはHUGOのFrontMatterで設定したTitleが呼び出されます。


その他の条件分岐も設定していきます

<meta name="keywords" content="{{ with .Params.Keyword }}{{ . }}{{ else }}{{ .Site.Params.Keyword }}{{ end }}">

<meta name="description" content="{{ with .Params.Description }}{{ . }}{{ else }}{{ .Site.Params.Description }}{{ end }}">
<meta property="og:title" content="{{if .IsHome}}{{ .Site.Params.homeTitle }}{{ else }}{{ .Title }}{{ end }} | {{ .Site.Params.SiteName }}">
<meta property="og:description" content="{{ with .Params.excerpt }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
<meta property="og:url" content="{{ .Permalink }}">
<meta property="og:image" content="{{ .Site.BaseURL }}{{ with .Params.ogp }}{{ . }}{{ else }}images/ogp.jpg{{ end }}">
<meta property="og:type" content="{{if .IsHome}}website{{ else }}article{{ end }}">
<meta property="og:site_name" content="{{ .Site.Params.SiteName }}">
<meta property="og:locale" content="{{ .Site.Params.LanguageCode }}">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{if .IsHome}}{{ .Site.Params.homeTitle }}{{ else }}{{ .Title }}{{ end }} | {{ .Site.Params.SiteName }}">
<meta name="twitter:description" content="{{ with .Params.excerpt }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
<meta name="twitter:image:src" content="{{ .Site.BaseURL }}{{ with .Params.ogp }}{{ . }}{{ else }}images/twitter_ogp.jpg{{ end }}">
<meta name="twitter:domain" content="{{ .Site.Params.Domain }}">

<meta name="keywords" content="{{ with .Params.Keyword }}{{ . }}{{ else }}{{ .Site.Params.Keyword }}{{ end }}">

上記の条件分岐の場合、HUGOのFrontMatter内にkeywordがあれば呼び出し、ない場合はconfig.tomlで設定した、Keywordが呼び出されます。

---

title: "title"
keyword: "keywordが入ります"
date: 2018-04-05
categories: ['photos']
caption: "Photoshop"
eyecatch: '/images/photos/photo01_firstview_ja.png'
ogp: 'images/photos/photo01_firstview.png'
url: '/photos/photo01/'
draft: false
---

上記の場合は、keywordが入りますが呼び出され、もしない場合はconfig.tomlで設定した、Keywordが呼び出されます。


部品をコンポーネント化していく

HUGOのPartialを使って、繰り返し使いそうな部品はコンポーネント化しておきます。

<!DOCTYPE html>

<html lang="{{ .Site.Params.LanguageCode }}">
<head>
<meta charset="UTF-8">
<title>{{if .IsHome}}{{ .Site.Params.homeTitle }}{{ else }}{{ .Title }}{{ end }} | {{ .Site.Params.SiteName }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<meta name="keywords" content="{{ with .Params.Keyword }}{{ . }}{{ else }}{{ .Site.Params.Keyword }}{{ end }}">
<meta name="description" content="{{ with .Params.Description }}{{ . }}{{ else }}{{ .Site.Params.Description }}{{ end }}">
{{ partial "ogp.html" . }}
{{ partial "styles.html" . }}
</head>


多言語対応していく

作っていく途中で多言語対応をしたくなったので、やってみました。

これが、HUGOの目玉機能の一つです。

参考にしたポートフォリオは多言語対応していなかったので、Githubを検索しまくって、参考になりそうなRepositoryを探します。


SkycoinのRepositoryを真似る

Skycoinのブログが、一番機能的に豊富で、わかりやすい構成になっていたので、

SkycoinのブログのRepositoryを真似ることにしました。


Netlifyに対応させていく

最初はGithub Pagesを使ってサイトを公開していましたが、以下の理由から、Netlifyに乗り換えました。


  • 独自ドメインのSSL対応が大変

  • 毎回buildコマンドを打つのが面倒になった

  • Formを使ってみたくなった

Formは、Netlifymが提供しているNetlify Formsを使って、簡単に導入することができました。

<div class="form__wrapper">

<form name="contact" netlify-honeypot="bot-field" action="thank-you" method="post" netlify="true">
<input type="hidden" name="form-name" value="contact" />
<h2>{{ i18n "formTitle" }}</h2>
<div class="field__container">
<div class="field__contents">
<div class="mc-field-group field__input">
<div class="form__label__wrapper">
<figure class="gopher__wrapper"><img src="{{ .Site.BaseURL }}images/icon/gopher_h.svg" alt=""></figure>
<label class="form__label">{{ i18n "formName" }}<span class="span__required">{{ i18n "formRequired" }}</span></label>
</div>
<input type="text" name="NAME" required>
</div>
<div class="mc-field-group field__input">
<div class="form__label__wrapper">
<figure class="gopher__wrapper"><img src="{{ .Site.BaseURL }}images/icon/gopher_u.svg" alt=""></figure>
<label class="form__label">{{ i18n "formMailaddress" }}<span class="span__required">{{ i18n "formRequired" }}</span></label>
</div>
<input type="email" name="EMAIL" required>
</div>
</div>
<div class="field__contents">
<div class="mc-field-group field__textarea">
<div class="form__label__wrapper">
<figure class="gopher__wrapper"><img src="{{ .Site.BaseURL }}images/icon/gopher_o.svg" alt=""></figure>
<figure class="gopher__wrapper"><img src="{{ .Site.BaseURL }}images/icon/gopher_g.svg" alt=""></figure>
<label class="form__label">{{ i18n "formInquiry" }}<span class="span__required">{{ i18n "formRequired" }}</span></label>
</div>
<textarea name="Message" cols="30" rows="10" required></textarea>
</div>
</div>
</div>
<div class="form__button__wrapper">
<button class="submit__button" type="submit">{{ i18n "formSubmit" }}</button>
</div>
</form>
</div>


まとめ

HUGOはシンプルだが多機能、かつ動作も速く、

PostCSSは設定が大変だが、これもNode製だから動作も早く、プラグインを組み合わせて自分だけのCSSプリプロセッサーを作ることができます。

Netlifyは、ただのホスティングサービスだけでなく、静的サイトジェネレーターの弱点であるFormまで補ってくれる、とても素晴らしいサービスでした。