Jekyll 静态站点完全教程 / 第12章:部署方案
第12章:部署方案
12.1 部署概述
Jekyll 生成的是纯静态文件(HTML/CSS/JS),可以部署到任何支持静态文件托管的平台。
部署方案对比
| 平台 | 免费额度 | 自定义域名 | HTTPS | 构建速度 | 插件限制 |
|---|
| GitHub Pages | 无限(公开仓库) | ✅ | ✅ | 中等 | 有白名单 |
| Netlify | 100GB/月 | ✅ | ✅ | 快 | 无 |
| Vercel | 100GB/月 | ✅ | ✅ | 极快 | 无 |
| Cloudflare Pages | 无限请求 | ✅ | ✅ | 极快 | 无 |
| AWS S3 + CloudFront | 按量付费 | ✅ | ✅ | — | 无 |
| 自托管 Nginx | — | ✅ | 自配置 | — | 无 |
12.2 GitHub Pages 部署
方式一:直接推送(简单)
# 1. 初始化仓库
git init
git add .
git commit -m "Initial site"
# 2. 推送到 GitHub
git remote add origin https://github.com/username/username.github.io.git
git push -u origin main
# 3. GitHub 自动构建
# 访问 https://username.github.io
方式二:GitHub Actions(推荐)
# .github/workflows/jekyll.yml
name: Deploy Jekyll Site
on:
push:
branches: [main]
pull_request:
branches: [main]
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.2'
bundler-cache: true
- name: Setup Pages
id: pages
uses: actions/configure-pages@v4
- 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@v3
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@v4
自定义域名配置
# 1. 在仓库根目录创建 CNAME 文件
echo "blog.example.com" > CNAME
# 2. DNS 配置(A 记录)
# 185.199.108.153
# 185.199.109.153
# 185.199.110.153
# 185.199.111.153
# 3. 或 CNAME 记录
# blog.example.com → username.github.io
注意事项:
- GitHub Pages 免费版仅支持公开仓库
- 使用 GitHub Actions 构建可绕过插件白名单限制
CNAME 文件必须在根目录且内容不含 https://
12.3 Netlify 部署
通过 Web 界面
- 登录 Netlify
- 点击 “New site from Git”
- 选择 GitHub 仓库
- 配置构建设置:
- Build command:
jekyll build - Publish directory:
_site
- 点击 “Deploy site”
通过 netlify.toml 配置
# netlify.toml
[build]
command = "jekyll build"
publish = "_site"
[build.environment]
RUBY_VERSION = "3.2.2"
JEKYLL_ENV = "production"
# 重定向规则
[[redirects]]
from = "/old-page"
to = "/new-page"
status = 301
# 自定义域名 + HTTPS(Netlify 自动配置)
# 在 Netlify 控制面板中添加自定义域名
# Headers 配置
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
Referrer-Policy = "strict-origin-when-cross-origin"
Cache-Control = "public, max-age=3600"
[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
Netlify 优势
| 特性 | 说明 |
|---|
| 预览部署 | 每个 PR 自动生成预览链接 |
| 无插件限制 | 可使用任意 Jekyll 插件 |
| 表单处理 | 内置 Netlify Forms |
| 函数 | 支持 Serverless Functions |
| 身份认证 | Netlify Identity |
12.4 Vercel 部署
vercel.json 配置
{
"buildCommand": "jekyll build",
"outputDirectory": "_site",
"installCommand": "bundle install",
"framework": null
}
部署步骤
# 1. 安装 Vercel CLI
npm i -g vercel
# 2. 登录
vercel login
# 3. 部署
vercel
# 4. 生产部署
vercel --prod
GitHub 集成
- 访问 vercel.com
- Import Git Repository
- 选择 Jekyll 仓库
- Framework Preset: Other
- Build Command:
jekyll build - Output Directory:
_site
12.5 Cloudflare Pages 部署
配置
Build command: jekyll build
Build output directory: _site
Environment variables:
RUBY_VERSION: 3.2.2
优势
- 无限请求、无限带宽
- 全球 CDN
- 自动 HTTPS
- 零配置部署
12.6 自托管部署
Nginx 配置
# /etc/nginx/sites-available/my-jekyll-site
server {
listen 80;
server_name blog.example.com;
root /var/www/jekyll-site;
index index.html;
# 开启 gzip 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
gzip_min_length 256;
# 静态资源缓存
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# HTML 不缓存(保证内容更新)
location ~* \.html$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# 自定义 404
error_page 404 /404.html;
location = /404.html {
internal;
}
# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# 处理永久链接(去掉 .html 后缀)
location / {
try_files $uri $uri.html $uri/ =404;
}
}
自动部署脚本
#!/bin/bash
# deploy.sh
set -e
SITE_DIR="/var/www/jekyll-site"
BUILD_DIR="/tmp/jekyll-build"
REPO_DIR="/opt/jekyll-site"
echo "📦 Pulling latest changes..."
cd "$REPO_DIR"
git pull origin main
echo "🔧 Installing dependencies..."
bundle install --deployment --without development
echo "🏗️ Building site..."
JEKYLL_ENV=production bundle exec jekyll build --destination "$BUILD_DIR"
echo "🚀 Deploying..."
rsync -avz --delete "$BUILD_DIR/" "$SITE_DIR/"
echo "🔄 Reloading Nginx..."
sudo systemctl reload nginx
echo "✅ Deploy complete!"
Systemd 服务(定时构建)
# /etc/systemd/system/jekyll-build.service
[Unit]
Description=Jekyll Site Build
After=network.target
[Service]
Type=oneshot
User=jekyll
WorkingDirectory=/opt/jekyll-site
ExecStart=/opt/jekyll-site/deploy.sh
# /etc/systemd/system/jekyll-build.timer
[Unit]
Description=Run Jekyll build every hour
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
12.7 CI/CD 流水线
GitHub Actions 完整工作流
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# 代码检查
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: HTMLProofer check
run: |
bundle exec jekyll build
bundle exec htmlproofer ./_site --disable-external --allow-hash-href
# 构建测试
build:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['3.1', '3.2', '3.3']
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true
- name: Build
run: bundle exec jekyll build
- name: Test output
run: |
test -f _site/index.html
test -d _site/assets
# 部署(仅 main 分支)
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [lint, build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Build
run: JEKYLL_ENV=production bundle exec jekyll build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v2
with:
publish-dir: './_site'
production-branch: main
github-token: ${{ secrets.GITHUB_TOKEN }}
deploy-message: "Deploy from GitHub Actions"
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
GitLab CI 配置
# .gitlab-ci.yml
image: ruby:3.2
cache:
paths:
- vendor/
before_script:
- bundle install --path vendor
stages:
- build
- deploy
build:
stage: build
script:
- bundle exec jekyll build --destination ./public
artifacts:
paths:
- public
pages:
stage: deploy
script:
- echo "Deploying to GitLab Pages"
artifacts:
paths:
- public
only:
- main
12.8 SSL/HTTPS 配置
Let’s Encrypt(自托管)
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx
# 获取证书
sudo certbot --nginx -d blog.example.com
# 自动续期
sudo certbot renew --dry-run
平台托管 HTTPS
| 平台 | HTTPS 配置 |
|---|
| GitHub Pages | 自动(github.io 域名)或 Let’s Encrypt(自定义域名) |
| Netlify | 自动 Let’s Encrypt |
| Vercel | 自动 |
| Cloudflare Pages | 自动 |
12.9 部署检查清单
## 部署前检查
- [ ] `bundle exec jekyll build` 无错误
- [ ] `bundle exec jekyll serve` 本地预览正常
- [ ] 所有链接有效(htmlproofer 检查)
- [ ] 图片路径正确(使用 `relative_url` 过滤器)
- [ ] `baseurl` 配置正确
- [ ] `_config.yml` 中 `url` 设置为生产域名
- [ ] `JEKYLL_ENV=production`
- [ ] SEO 元标签完整
- [ ] sitemap.xml 可访问
- [ ] robots.txt 配置正确
- [ ] HTTPS 正常工作
- [ ] 自定义域名 DNS 已配置
- [ ] 404 页面正常显示
12.10 扩展阅读
本章小结
| 要点 | 说明 |
|---|
| GitHub Pages | 最简单,免费,有插件限制 |
| Netlify | 功能丰富,无插件限制,PR 预览 |
| Vercel | 极快构建,全球 CDN |
| 自托管 | 完全控制,需要运维 |
| CI/CD | GitHub Actions 实现自动化构建和部署 |
| HTTPS | 大多数平台自动配置 |
下一章:Docker 化构建