Netlify

WebホスティングJAMstackEdge FunctionsCI/CD静的サイトフォーム処理ID管理

Webホスティングプラットフォーム

Netlify

概要

NetlifyはJamstackサイト向けのクラウドプラットフォームです。継続的デプロイメント、フォーム処理、ID管理、Edge Functions、CMS統合を提供する包括的なソリューションとして、Jamstackエコシステムの先駆者として確固たる地位を維持しています。開発者向け機能の豊富さとエコシステムの充実により、静的サイト開発において継続的に支持されています。

詳細

2014年に設立されたNetlifyは、JAMstack(JavaScript、APIs、Markup)アーキテクチャを普及させた先駆的企業です。Git連携による自動デプロイ、Form handling、Identity management、Edge Functions、A/Bテスト機能などを統合的に提供し、静的サイト開発の全工程をサポート。特にフロントエンド開発者向けの直感的なUI/UXと、豊富なプラグインエコシステムが特徴。Netlify CMSやNetlify Functionsなど、開発者の生産性向上に焦点を当てた機能拡張を継続的に行っており、中小規模のプロジェクトから大規模なエンタープライズサイトまで幅広く対応しています。

メリット・デメリット

メリット

  • 包括的なJAMstackソリューション: デプロイからフォーム処理、認証まで一元管理
  • 優秀なGit統合: ブランチベースのプレビューとロールバック機能
  • 豊富なプラグインエコシステム: 数百のプラグインによる機能拡張
  • Form handling: サーバーレスフォーム処理とスパム対策機能
  • Identity management: OAuth、JWT認証の簡単実装
  • A/Bテスト機能: 組み込みの分割テスト機能
  • 優れたドキュメント: 充実した学習リソースとコミュニティサポート

デメリット

  • ビルド時間制限: 無料プランでは月300分まで
  • 帯域幅制限: トラフィック増加時の追加課金
  • 複雑な価格体系: 機能や使用量による段階的課金
  • 学習コストの高さ: 高機能ゆえの初期学習負担

参考ページ

書き方の例

基本的なセットアップとプロジェクト設定

# Netlify CLIのインストール
npm install -g netlify-cli

# ログインとサイト初期化
netlify login
netlify init

# 開発サーバーの起動
netlify dev

# ローカルでFunctionsをテスト
netlify functions:serve
# netlify.toml - 基本設定
[build]
  publish = "dist"
  command = "npm run build"
  functions = "netlify/functions"

[build.environment]
  NODE_VERSION = "18"
  NPM_VERSION = "9"

[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"

静的サイトデプロイ

# 手動デプロイ
netlify deploy --prod --dir=dist

# 特定ブランチからのデプロイ
netlify deploy --alias=staging

# ドラッグ&ドロップデプロイ
netlify deploy --dir=./build --prod
# GitHub Actions での自動デプロイ
name: Deploy to Netlify
on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build
        run: npm run build
      
      - name: Deploy to Netlify
        uses: nwtgck/[email protected]
        with:
          publish-dir: './dist'
          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 }}

フレームワーク統合(Next.js、React、Vue)

// netlify/functions/api.js - Next.js API Routes風
exports.handler = async (event, context) => {
  const { httpMethod, path, body } = event;
  
  // CORSヘッダー
  const headers = {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Headers': 'Content-Type',
    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE'
  };
  
  if (httpMethod === 'OPTIONS') {
    return { statusCode: 200, headers, body: '' };
  }
  
  try {
    let response;
    
    switch (httpMethod) {
      case 'GET':
        response = await handleGet(path);
        break;
      case 'POST':
        response = await handlePost(JSON.parse(body));
        break;
      default:
        return {
          statusCode: 405,
          headers,
          body: JSON.stringify({ error: 'Method not allowed' })
        };
    }
    
    return {
      statusCode: 200,
      headers: { ...headers, 'Content-Type': 'application/json' },
      body: JSON.stringify(response)
    };
  } catch (error) {
    return {
      statusCode: 500,
      headers,
      body: JSON.stringify({ error: error.message })
    };
  }
};
# Nuxt.js設定
[build]
  command = "npm run generate"
  publish = "dist"

[build.environment]
  NODE_VERSION = "18"

[[redirects]]
  from = "/_nuxt/*"
  to = "/_nuxt/:splat"
  status = 200

# SPA mode用設定
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

カスタムドメインとSSL

# カスタムドメインの追加
netlify domains:create example.com
netlify domains:add example.com

# SSL証明書の設定(自動)
# NetlifyはLet's Encryptを自動で設定

# DNS設定の確認
netlify dns
# netlify.toml - ドメイン関連設定
[[redirects]]
  from = "https://www.example.com/*"
  to = "https://example.com/:splat"
  status = 301
  force = true

[[headers]]
  for = "/*"
  [headers.values]
    Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
    Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline'"

サーバーレスファンクションとAPI

// netlify/functions/hello.js - 基本的なFunction
exports.handler = async (event, context) => {
  const { name = 'World' } = event.queryStringParameters || {};
  
  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
      'Cache-Control': 'public, max-age=60'
    },
    body: JSON.stringify({
      message: `Hello ${name}!`,
      timestamp: new Date().toISOString(),
      source: 'Netlify Functions'
    })
  };
};
// netlify/functions/users.ts - TypeScript Function
import { Handler } from '@netlify/functions';
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_ANON_KEY!
);

export const handler: Handler = async (event, context) => {
  const { httpMethod, body, path } = event;
  
  try {
    switch (httpMethod) {
      case 'GET':
        const { data: users, error } = await supabase
          .from('users')
          .select('*');
        
        if (error) throw error;
        
        return {
          statusCode: 200,
          body: JSON.stringify(users)
        };
        
      case 'POST':
        const userData = JSON.parse(body || '{}');
        const { data: newUser, error: insertError } = await supabase
          .from('users')
          .insert([userData])
          .select();
        
        if (insertError) throw insertError;
        
        return {
          statusCode: 201,
          body: JSON.stringify(newUser)
        };
        
      default:
        return {
          statusCode: 405,
          body: JSON.stringify({ error: 'Method not allowed' })
        };
    }
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify({ error: error.message })
    };
  }
};

CI/CDと本番最適化

# netlify.toml - 最適化設定
[build]
  command = "npm run build"
  publish = "dist"
  functions = "netlify/functions"
  
[build.processing]
  skip_processing = false

[build.processing.css]
  bundle = true
  minify = true

[build.processing.js]
  bundle = true
  minify = true

[build.processing.html]
  pretty_urls = true

[build.processing.images]
  compress = true

# プレビューデプロイの設定
[context.deploy-preview]
  command = "npm run build:preview"
  
[context.branch-deploy]
  command = "npm run build:staging"

# 環境変数
[context.production.environment]
  NODE_ENV = "production"
  GATSBY_ACTIVE_ENV = "production"
// netlify/functions/build-hook.js - ビルドトリガー
const crypto = require('crypto');

exports.handler = async (event, context) => {
  // Webhook認証
  const signature = event.headers['x-netlify-signature'];
  const payload = event.body;
  const secret = process.env.WEBHOOK_SECRET;
  
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');
  
  if (signature !== expectedSignature) {
    return {
      statusCode: 401,
      body: JSON.stringify({ error: 'Unauthorized' })
    };
  }
  
  // CMS更新時の自動ビルド
  const buildHookUrl = process.env.BUILD_HOOK_URL;
  
  try {
    const response = await fetch(buildHookUrl, {
      method: 'POST',
      body: JSON.stringify({ trigger: 'CMS update' })
    });
    
    return {
      statusCode: 200,
      body: JSON.stringify({ 
        message: 'Build triggered successfully',
        buildId: response.headers.get('x-netlify-build-id')
      })
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify({ error: error.message })
    };
  }
};
# Netlify CLI コマンド集
netlify status              # サイト状況確認
netlify build               # ローカルビルド
netlify deploy --build      # ビルド+デプロイ
netlify functions:list      # Functions一覧
netlify addons:list         # アドオン確認
netlify env:list            # 環境変数確認
netlify logs:functions      # Function ログ確認