Jekyll
GitHub Pages標準のRuby製SSG。49k超のGitHubスターを持ち、シンプルなブログやドキュメントサイトに最適。
トレンド・動向
GitHub Pagesとの完全統合により個人プロジェクトやオープンソースドキュメントで根強い人気を維持。
# 静的サイトジェネレータ
Jekyll
## 概要
JekyllはRuby製の「ブログ指向静的サイトジェネレータ」として2008年にリリースされた、最も歴史と実績のあるSSGです。49k超のGitHubスターを誇り、GitHub Pagesの標準エンジンとして採用されているため、GitHubとの完全統合により無料でサイトを公開可能。シンプルなMarkdownとLiquidテンプレートによるコンテンツ作成、豊富なプラグインエコシステム、file-based CMSライクな管理方式により、個人ブログから企業サイトまで幅広く活用されています。
## 詳細
Jekyll 2025年版は静的サイトジェネレータのパイオニアとして確固たる地位を維持し、特にGitHub Pagesとの完全統合により開発者コミュニティで絶大な支持を獲得しています。Rubyエコシステムの成熟した開発環境を活用し、Liquidテンプレートエンジンによる柔軟なコンテンツ処理、YAMLフロントマターによるメタデータ管理、豊富なプラグインライブラリによる機能拡張を提供。Markdown、HTML、CSS、JavaScriptファイルから完全な静的Webサイトを生成し、高いパフォーマンスとセキュリティを実現します。
### 主な特徴
- **GitHub Pages完全統合**: 標準エンジンとして無料ホスティングと自動デプロイ
- **ブログ指向設計**: パーマリンク、カテゴリ、投稿、カスタムレイアウトがファーストクラス
- **Liquidテンプレート**: 動的コンテンツ生成と柔軟なテンプレート処理
- **豊富なプラグインエコシステム**: Ruby Gemによる機能拡張
- **File-based CMS**: データベース不要のファイルベース管理
- **高度なカスタマイズ性**: レイアウト、インクルード、SASS対応
## メリット・デメリット
### メリット
- GitHub Pagesとの完全統合による無料ホスティングと自動デプロイメント
- 17年の開発実績による成熟したエコシステムと豊富な学習リソース
- 豊富なプラグインライブラリによる高度な機能拡張とカスタマイズ性
- シンプルなMarkdown + YAMLによる直感的なコンテンツ管理
- 大規模なコミュニティサポートとテーマの豊富さ
- 企業やオープンソースプロジェクトでの採用実績と信頼性
### デメリット
- Ruby環境が必要でローカル開発環境構築の複雑さ
- 大規模サイトでのビルド速度がHugoやZola比較で劣る
- GitHub Pagesのsafeモードでプラグイン制限あり
- モダンなJavaScript/TypeScriptエコシステムとの統合性
- Ruby依存によるCI/CD環境での設定複雑さ
- 最新のWeb開発トレンドへの対応速度
## 参考ページ
- [Jekyll 公式サイト](https://jekyllrb.com/)
- [Jekyll GitHub リポジトリ](https://github.com/jekyll/jekyll)
- [GitHub Pages ドキュメント](https://docs.github.com/pages/)
## 書き方の例
### インストールとセットアップ
```bash
# Rubyと依存関係のインストール(Ubuntu)
sudo apt-get install ruby-full build-essential zlib1g-dev
# ユーザー用Gem設定
echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc
echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc
echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# JekyllとBundlerのインストール
gem install jekyll bundler
# 新しいサイトの作成
jekyll new my-awesome-site
cd my-awesome-site
# Gemfileの確認
cat Gemfile
# 依存関係のインストール
bundle install
# ローカル開発サーバーの起動
bundle exec jekyll serve
# => http://localhost:4000 でアクセス可能
# GitHub Pagesとの互換性確認
bundle exec jekyll serve --baseurl=""
```
### 基本設定とサイト構成
```yaml
# _config.yml - 基本設定
title: My Jekyll Website
email: [email protected]
description: >-
シンプルで美しいJekyllサイトです。
ブログや技術ドキュメントに最適。
baseurl: "" # サブパス(例:/blog)
url: "https://username.github.io" # ベースURL
# ビルド設定
markdown: kramdown
highlighter: rouge
theme: minima
# プラグイン設定
plugins:
- jekyll-feed
- jekyll-sitemap
- jekyll-seo-tag
# 除外ファイル
exclude:
- Gemfile
- Gemfile.lock
- node_modules
- vendor/bundle/
- vendor/cache/
- vendor/gems/
- vendor/ruby/
# コレクション設定
collections:
projects:
output: true
permalink: /:collection/:name/
# デフォルト設定
defaults:
- scope:
path: ""
type: "posts"
values:
layout: "post"
author: "Your Name"
- scope:
path: ""
type: "pages"
values:
layout: "page"
```
### 投稿とページの作成
```markdown
---
# _posts/2025-01-15-jekyll-tutorial.md
layout: post
title: "Jekyll入門ガイド"
date: 2025-01-15 10:00:00 +0900
categories: [tutorial, jekyll]
tags: [static-site, github-pages, ruby]
author: "Your Name"
excerpt: "JekyllでWebサイトを構築する方法を解説します。"
---
# Jekyll入門ガイド
JekyllはRuby製の静的サイトジェネレータです。
## 特徴
- GitHub Pagesとの完全統合
- Markdown + Liquidテンプレート
- 豊富なプラグインエコシステム
## コード例
```ruby
# Gemfile
source "https://rubygems.org"
gem "jekyll", "~> 4.2.0"
gem "minima", "~> 2.5"
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12"
gem "jekyll-sitemap"
gem "jekyll-seo-tag"
end
```
## まとめ
Jekyllを使用することで、シンプルで高速なWebサイトを構築できます。
---
# pages/about.md
---
layout: page
title: About
permalink: /about/
---
これはAboutページです。
会社情報や個人のプロフィールを記載できます。
## 連絡先
- Email: {{ site.email }}
- GitHub: [username](https://github.com/username)
```
### レイアウトとテンプレート
```html
<!-- _layouts/default.html -->
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: 'ja' }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page.title }} | {{ site.title }}</title>
<meta name="description" content="{{ page.excerpt | default: site.description | strip_html | normalize_whitespace | truncate: 160 | escape }}">
<link rel="stylesheet" href="{{ '/assets/main.css' | relative_url }}">
<link rel="canonical" href="{{ page.url | replace:'index.html','' | absolute_url }}">
{% feed_meta %}
{% seo %}
</head>
<body>
<header class="site-header" role="banner">
<div class="wrapper">
<a class="site-title" href="{{ '/' | relative_url }}">{{ site.title | escape }}</a>
<nav class="site-nav">
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger">
<span class="menu-icon">
<svg viewBox="0 0 18 15" width="18px" height="15px">
<path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
</svg>
</span>
</label>
<div class="trigger">
{% for my_page in site.pages %}
{% if my_page.title %}
<a class="page-link" href="{{ my_page.url | relative_url }}">{{ my_page.title | escape }}</a>
{% endif %}
{% endfor %}
</div>
</nav>
</div>
</header>
<main class="page-content" aria-label="Content">
<div class="wrapper">
{{ content }}
</div>
</main>
<footer class="site-footer h-card">
<div class="wrapper">
<div class="footer-col-wrapper">
<div class="footer-col footer-col-1">
<ul class="contact-list">
<li class="p-name">{{ site.title | escape }}</li>
{% if site.email %}
<li><a class="u-email" href="mailto:{{ site.email }}">{{ site.email }}</a></li>
{% endif %}
</ul>
</div>
<div class="footer-col footer-col-2">
{% include social.html %}
</div>
<div class="footer-col footer-col-3">
<p>{{ site.description | escape }}</p>
</div>
</div>
</div>
</footer>
</body>
</html>
<!-- _layouts/post.html -->
---
layout: default
---
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
<p class="post-meta">
<time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
{{ page.date | date: "%Y年%m月%d日" }}
</time>
{% if page.author %}
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
<span class="p-author h-card" itemprop="name">{{ page.author }}</span>
</span>
{% endif %}
</p>
</header>
<div class="post-content e-content" itemprop="articleBody">
{{ content }}
</div>
{% if site.disqus.shortname %}
{% include disqus_comments.html %}
{% endif %}
<a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
</article>
```
### プラグイン設定と拡張機能
```ruby
# Gemfile - プラグイン設定
source "https://rubygems.org"
gem "jekyll", "~> 4.2.0"
# テーマ
gem "minima", "~> 2.5"
# GitHub Pages互換
gem "github-pages", group: :jekyll_plugins
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12" # RSSフィード生成
gem "jekyll-sitemap" # サイトマップ生成
gem "jekyll-seo-tag" # SEOメタタグ
gem "jekyll-gist" # Gist埋め込み
gem "jekyll-paginate" # ページネーション
gem "jekyll-archives" # アーカイブページ
gem "jekyll-redirect-from" # リダイレクト設定
gem "jekyll-admin" # 管理画面(開発用)
end
```
```yaml
# _config.yml - プラグイン詳細設定
plugins:
- jekyll-feed
- jekyll-sitemap
- jekyll-seo-tag
- jekyll-gist
- jekyll-paginate
- jekyll-archives
- jekyll-redirect-from
# ページネーション設定
paginate: 5
paginate_path: "/blog/page:num/"
# アーカイブ設定
jekyll-archives:
enabled:
- categories
- tags
- year
- month
layout: archive
permalinks:
year: '/:year/'
month: '/:year/:month/'
day: '/:year/:month/:day/'
tag: '/tag/:name/'
category: '/category/:name/'
# SEO設定
title: My Jekyll Site
description: Awesome Jekyll powered website
url: "https://username.github.io"
author:
name: Your Name
email: [email protected]
twitter: username
social:
name: Your Name
links:
- https://twitter.com/username
- https://github.com/username
- https://linkedin.com/in/username
```
### 高度な機能とカスタマイズ
```yaml
# _config.yml - 高度な設定
# コレクション定義
collections:
projects:
output: true
permalink: /:collection/:name/
team:
output: false
# デフォルト値設定
defaults:
- scope:
path: ""
type: "posts"
values:
layout: "post"
author: "default-author"
show_excerpts: true
- scope:
path: "projects"
type: "projects"
values:
layout: "project"
- scope:
path: ""
type: "pages"
values:
layout: "page"
# Sass設定
sass:
sass_dir: _sass
style: compressed
# Kramdown設定
kramdown:
input: GFM
syntax_highlighter: rouge
syntax_highlighter_opts:
css_class: 'highlight'
span:
line_numbers: false
block:
line_numbers: true
# 除外設定
exclude:
- Gemfile
- Gemfile.lock
- node_modules
- vendor/
- .sass-cache/
- .jekyll-cache/
- gemfiles/
- README.md
- package.json
- package-lock.json
```
```liquid
<!-- _includes/navigation.html -->
<nav class="main-nav">
<ul>
<li><a href="{{ '/' | relative_url }}"
{% if page.url == '/' %}class="current"{% endif %}>Home</a></li>
<li><a href="{{ '/blog/' | relative_url }}"
{% if page.url contains '/blog/' %}class="current"{% endif %}>Blog</a></li>
<li><a href="{{ '/projects/' | relative_url }}"
{% if page.url contains '/projects/' %}class="current"{% endif %}>Projects</a></li>
<li><a href="{{ '/about/' | relative_url }}"
{% if page.url == '/about/' %}class="current"{% endif %}>About</a></li>
</ul>
</nav>
<!-- カスタムLiquidフィルター例 -->
{% assign sorted_posts = site.posts | sort: 'date' | reverse %}
{% for post in sorted_posts limit:5 %}
<article>
<h3><a href="{{ post.url | relative_url }}">{{ post.title }}</a></h3>
<time>{{ post.date | date: "%Y年%m月%d日" }}</time>
<p>{{ post.excerpt | strip_html | truncate: 150 }}</p>
</article>
{% endfor %}
<!-- 条件分岐とデータアクセス -->
{% if site.data.team %}
<section class="team">
<h2>チームメンバー</h2>
{% for member in site.data.team %}
<div class="member">
<h3>{{ member.name }}</h3>
<p>{{ member.role }}</p>
{% if member.bio %}
<p>{{ member.bio }}</p>
{% endif %}
</div>
{% endfor %}
</section>
{% endif %}
```
### GitHub Pages本番デプロイメント
```yaml
# .github/workflows/jekyll.yml - GitHub Actions
name: Build and deploy Jekyll site to GitHub Pages
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1'
bundler-cache: true
cache-version: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v3
- name: Build with Jekyll
run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
env:
JEKYLL_ENV: production
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
```
```bash
# 本番ビルドとデプロイ
# 1. ローカルでの本番環境テスト
JEKYLL_ENV=production bundle exec jekyll build
bundle exec jekyll serve --baseurl="" # GitHub Pages Project用
# 2. 手動デプロイ(独自サーバー)
JEKYLL_ENV=production bundle exec jekyll build
rsync -avz --delete _site/ [email protected]:/var/www/html/
# 3. Docker環境でのビルド
docker run --rm -v $(pwd):/srv/jekyll jekyll/jekyll:latest jekyll build
# 4. ビルド結果の確認
ls -la _site/
find _site -name "*.html" | head -10
```