强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第12章:部署方案

第12章:部署方案

12.1 部署概述

Jekyll 生成的是纯静态文件(HTML/CSS/JS),可以部署到任何支持静态文件托管的平台。

部署方案对比

平台免费额度自定义域名HTTPS构建速度插件限制
GitHub Pages无限(公开仓库)中等有白名单
Netlify100GB/月
Vercel100GB/月极快
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 界面

  1. 登录 Netlify
  2. 点击 “New site from Git”
  3. 选择 GitHub 仓库
  4. 配置构建设置:
    • Build command: jekyll build
    • Publish directory: _site
  5. 点击 “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 集成

  1. 访问 vercel.com
  2. Import Git Repository
  3. 选择 Jekyll 仓库
  4. Framework Preset: Other
  5. Build Command: jekyll build
  6. 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/CDGitHub Actions 实现自动化构建和部署
HTTPS大多数平台自动配置

下一章:Docker 化构建