netlify-deployment-platform

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Netlify Platform Skill

Netlify 平台技能


progressive_disclosure: entry_point: summary: "JAMstack deployment platform with serverless functions, forms, and identity" when_to_use: - "When deploying static sites and SPAs" - "When building JAMstack applications" - "When needing serverless functions" - "When requiring built-in forms and auth" quick_start: - "npm install -g netlify-cli" - "netlify login" - "netlify init" - "netlify deploy --prod" token_estimate: entry: 70-85 full: 3800-4800


progressive_disclosure: entry_point: summary: "JAMstack 部署平台,包含无服务器函数、表单和身份验证功能" when_to_use: - "部署静态网站和单页应用(SPA)时" - "构建JAMstack应用程序时" - "需要无服务器函数时" - "需要内置表单和身份验证时" quick_start: - "npm install -g netlify-cli" - "netlify login" - "netlify init" - "netlify deploy --prod" token_estimate: entry: 70-85 full: 3800-4800

Netlify Fundamentals

Netlify 基础概念

Core Concepts

核心概念

  • Sites: Static sites deployed to Netlify's global CDN
  • Builds: Automated build process triggered by Git commits
  • Deploy Contexts: production, deploy-preview, branch-deploy
  • Atomic Deploys: All-or-nothing deployments with instant rollback
  • Instant Cache Invalidation: CDN cache cleared automatically
  • Sites: 部署到Netlify全球CDN的静态网站
  • Builds: 由Git提交触发的自动化构建流程
  • Deploy Contexts: production(生产环境)、deploy-preview(部署预览)、branch-deploy(分支部署)
  • Atomic Deploys: 全量生效或回退的原子化部署,支持即时回滚
  • Instant Cache Invalidation: CDN缓存自动清除

Platform Benefits

平台优势

  • Global CDN: Built-in content delivery network
  • Continuous Deployment: Auto-deploy from Git
  • HTTPS by Default: Free SSL certificates
  • Deploy Previews: Preview every pull request
  • Serverless Functions: Backend logic without servers
  • Forms & Identity: Built-in features for common needs
  • Global CDN: 内置内容分发网络
  • Continuous Deployment: 从Git自动部署
  • HTTPS by Default: 免费SSL证书
  • Deploy Previews: 预览每个拉取请求的效果
  • Serverless Functions: 无需服务器的后端逻辑
  • Forms & Identity: 满足常见需求的内置功能

Static Site Deployment

静态站点部署

Supported Frameworks

支持的框架

bash
undefined
bash
undefined

React (Create React App, Vite)

React (Create React App, Vite)

Build command: npm run build Publish directory: build (CRA) or dist (Vite)
Build command: npm run build Publish directory: build (CRA) or dist (Vite)

Next.js (Static Export)

Next.js (Static Export)

Build command: npm run build && npm run export Publish directory: out
Build command: npm run build && npm run export Publish directory: out

Vue.js

Vue.js

Build command: npm run build Publish directory: dist
Build command: npm run build Publish directory: dist

Gatsby

Gatsby

Build command: gatsby build Publish directory: public
Build command: gatsby build Publish directory: public

Hugo

Hugo

Build command: hugo Publish directory: public
Build command: hugo Publish directory: public

Svelte/SvelteKit

Svelte/SvelteKit

Build command: npm run build Publish directory: build
undefined
Build command: npm run build Publish directory: build
undefined

Manual Deployment

手动部署

bash
undefined
bash
undefined

Install Netlify CLI

安装Netlify CLI

npm install -g netlify-cli
npm install -g netlify-cli

Login to Netlify

登录Netlify

netlify login
netlify login

Initialize site

初始化站点

netlify init
netlify init

Deploy draft (preview URL)

部署草稿版本(预览URL)

netlify deploy
netlify deploy

Deploy to production

部署到生产环境

netlify deploy --prod
netlify deploy --prod

Deploy with build

构建并部署

netlify deploy --build --prod
undefined
netlify deploy --build --prod
undefined

netlify.toml Configuration

netlify.toml 配置

Basic Configuration

基础配置

toml
undefined
toml
undefined

netlify.toml

netlify.toml

[build]

Build command

command = "npm run build"

Publish directory

publish = "dist"

Functions directory

functions = "netlify/functions"
[build]

构建命令

command = "npm run build"

发布目录

publish = "dist"

函数目录

functions = "netlify/functions"

Production context

生产环境上下文

[context.production] command = "npm run build:prod"
[context.production.environment] NODE_ENV = "production" API_URL = "https://api.example.com"
[context.production] command = "npm run build:prod"
[context.production.environment] NODE_ENV = "production" API_URL = "https://api.example.com"

Deploy Preview context

部署预览上下文

[context.deploy-preview] command = "npm run build:preview"
[context.deploy-preview] command = "npm run build:preview"

Branch deploys

分支部署

[context.branch-deploy] command = "npm run build"
undefined
[context.branch-deploy] command = "npm run build"
undefined

Build Settings

构建设置

toml
[build]
  command = "npm run build"
  publish = "dist"

  # Base directory for monorepos
  base = "packages/web"

  # Ignore builds on certain changes
  ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/web"

[build.environment]
  NODE_VERSION = "18"
  NPM_VERSION = "9"
  RUBY_VERSION = "3.1"
toml
[build]
  command = "npm run build"
  publish = "dist"

  # 单仓库多项目(Monorepo)的基础目录
  base = "packages/web"

  # 特定变更时跳过构建
  ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/web"

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

Advanced Build Configuration

高级构建配置

toml
[build]
  command = "npm run build"
  publish = "dist"

  # Build processing
  [build.processing]
    skip_processing = false
  [build.processing.css]
    bundle = true
    minify = true
  [build.processing.js]
    bundle = true
    minify = true
  [build.processing.images]
    compress = true
toml
[build]
  command = "npm run build"
  publish = "dist"

  # 构建处理
  [build.processing]
    skip_processing = false
  [build.processing.css]
    bundle = true
    minify = true
  [build.processing.js]
    bundle = true
    minify = true
  [build.processing.images]
    compress = true

Environment Variables

环境变量

Setting Variables

设置变量

bash
undefined
bash
undefined

Via CLI

通过CLI设置

netlify env:set API_KEY "secret-value" netlify env:set NODE_ENV "production"
netlify env:set API_KEY "secret-value" netlify env:set NODE_ENV "production"

List variables

列出变量

netlify env:list
netlify env:list

Import from .env file

从.env文件导入

netlify env:import .env
undefined
netlify env:import .env
undefined

Variable Scopes

变量作用域

toml
undefined
toml
undefined

netlify.toml

netlify.toml

[context.production.environment] API_URL = "https://api.production.com" ENABLE_ANALYTICS = "true"
[context.deploy-preview.environment] API_URL = "https://api.staging.com" ENABLE_ANALYTICS = "false"
[context.branch-deploy.environment] API_URL = "https://api.dev.com"
undefined
[context.production.environment] API_URL = "https://api.production.com" ENABLE_ANALYTICS = "true"
[context.deploy-preview.environment] API_URL = "https://api.staging.com" ENABLE_ANALYTICS = "false"
[context.branch-deploy.environment] API_URL = "https://api.dev.com"
undefined

Accessing in Build

构建时访问变量

javascript
// During build
const apiUrl = process.env.API_URL;

// Client-side (must be prefixed)
const publicKey = process.env.REACT_APP_PUBLIC_KEY;
javascript
// 构建过程中访问
const apiUrl = process.env.API_URL;

// 客户端访问(必须添加前缀)
const publicKey = process.env.REACT_APP_PUBLIC_KEY;

Serverless Functions

无服务器函数

Function Structure

函数结构

javascript
// netlify/functions/hello.js
exports.handler = async (event, context) => {
  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      message: 'Hello from Netlify Function',
      path: event.path,
      method: event.httpMethod,
    }),
  };
};
javascript
// netlify/functions/hello.js
exports.handler = async (event, context) => {
  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      message: 'Hello from Netlify Function',
      path: event.path,
      method: event.httpMethod,
    }),
  };
};

TypeScript Functions

TypeScript 函数

typescript
// netlify/functions/api.ts
import { Handler, HandlerEvent, HandlerContext } from '@netlify/functions';

interface RequestBody {
  name: string;
  email: string;
}

export const handler: Handler = async (
  event: HandlerEvent,
  context: HandlerContext
) => {
  if (event.httpMethod !== 'POST') {
    return {
      statusCode: 405,
      body: 'Method Not Allowed',
    };
  }

  const { name, email }: RequestBody = JSON.parse(event.body || '{}');

  return {
    statusCode: 200,
    body: JSON.stringify({
      message: `Hello ${name}`,
      email,
    }),
  };
};
typescript
// netlify/functions/api.ts
import { Handler, HandlerEvent, HandlerContext } from '@netlify/functions';

interface RequestBody {
  name: string;
  email: string;
}

export const handler: Handler = async (
  event: HandlerEvent,
  context: HandlerContext
) => {
  if (event.httpMethod !== 'POST') {
    return {
      statusCode: 405,
      body: 'Method Not Allowed',
    };
  }

  const { name, email }: RequestBody = JSON.parse(event.body || '{}');

  return {
    statusCode: 200,
    body: JSON.stringify({
      message: `Hello ${name}`,
      email,
    }),
  };
};

Advanced Function Patterns

高级函数模式

javascript
// netlify/functions/database.js
const { MongoClient } = require('mongodb');

let cachedDb = null;

async function connectToDatabase() {
  if (cachedDb) return cachedDb;

  const client = await MongoClient.connect(process.env.MONGODB_URI);
  cachedDb = client.db();
  return cachedDb;
}

exports.handler = async (event) => {
  const db = await connectToDatabase();
  const users = await db.collection('users').find({}).toArray();

  return {
    statusCode: 200,
    body: JSON.stringify(users),
  };
};
javascript
// netlify/functions/database.js
const { MongoClient } = require('mongodb');

let cachedDb = null;

async function connectToDatabase() {
  if (cachedDb) return cachedDb;

  const client = await MongoClient.connect(process.env.MONGODB_URI);
  cachedDb = client.db();
  return cachedDb;
}

exports.handler = async (event) => {
  const db = await connectToDatabase();
  const users = await db.collection('users').find({}).toArray();

  return {
    statusCode: 200,
    body: JSON.stringify(users),
  };
};

Scheduled Functions

定时函数

javascript
// netlify/functions/scheduled.js
const { schedule } = require('@netlify/functions');

const handler = async () => {
  console.log('Running scheduled task');

  // Your scheduled logic
  await performBackup();

  return {
    statusCode: 200,
  };
};

// Run every day at midnight
exports.handler = schedule('0 0 * * *', handler);
javascript
// netlify/functions/scheduled.js
const { schedule } = require('@netlify/functions');

const handler = async () => {
  console.log('Running scheduled task');

  // 你的定时任务逻辑
  await performBackup();

  return {
    statusCode: 200,
  };
};

// 每天午夜运行
exports.handler = schedule('0 0 * * *', handler);

Background Functions

后台函数

javascript
// netlify/functions/background-task.js
// Auto-runs in background if response is 200 within 10s
exports.handler = async (event) => {
  // Long-running task
  await processLargeDataset();

  return {
    statusCode: 200,
  };
};

// Invoke: POST to /.netlify/functions/background-task
javascript
// netlify/functions/background-task.js
// 如果10秒内返回200,则自动在后台运行
exports.handler = async (event) => {
  // 长时间运行的任务
  await processLargeDataset();

  return {
    statusCode: 200,
  };
};

// 调用方式:POST请求到 /.netlify/functions/background-task

Netlify Forms

Netlify 表单

HTML Form

HTML 表单

html
<!-- Contact form -->
<form name="contact" method="POST" data-netlify="true">
  <input type="hidden" name="form-name" value="contact" />

  <label>Name: <input type="text" name="name" required /></label>
  <label>Email: <input type="email" name="email" required /></label>
  <label>Message: <textarea name="message" required></textarea></label>

  <button type="submit">Send</button>
</form>
html
<!-- 联系表单 -->
<form name="contact" method="POST" data-netlify="true">
  <input type="hidden" name="form-name" value="contact" />

  <label>姓名: <input type="text" name="name" required /></label>
  <label>邮箱: <input type="email" name="email" required /></label>
  <label>留言: <textarea name="message" required></textarea></label>

  <button type="submit">发送</button>
</form>

React Form

React 表单

jsx
// ContactForm.jsx
import { useState } from 'react';

export default function ContactForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: '',
  });

  const handleSubmit = async (e) => {
    e.preventDefault();

    const response = await fetch('/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        'form-name': 'contact',
        ...formData,
      }).toString(),
    });

    if (response.ok) {
      alert('Thank you for your message!');
    }
  };

  return (
    <form name="contact" onSubmit={handleSubmit} data-netlify="true">
      <input type="hidden" name="form-name" value="contact" />
      {/* Form fields */}
    </form>
  );
}
jsx
// ContactForm.jsx
import { useState } from 'react';

export default function ContactForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: '',
  });

  const handleSubmit = async (e) => {
    e.preventDefault();

    const response = await fetch('/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        'form-name': 'contact',
        ...formData,
      }).toString(),
    });

    if (response.ok) {
      alert('感谢您的留言!');
    }
  };

  return (
    <form name="contact" onSubmit={handleSubmit} data-netlify="true">
      <input type="hidden" name="form-name" value="contact" />
      {/* 表单字段 */}
    </form>
  );
}

Form Features

表单功能

html
<!-- Spam filtering with honeypot -->
<form name="contact" method="POST" data-netlify="true" data-netlify-honeypot="bot-field">
  <input type="hidden" name="form-name" value="contact" />
  <p class="hidden">
    <label>Don't fill this out: <input name="bot-field" /></label>
  </p>
  <!-- Form fields -->
</form>

<!-- reCAPTCHA v2 -->
<form name="contact" method="POST" data-netlify="true" data-netlify-recaptcha="true">
  <div data-netlify-recaptcha="true"></div>
  <button type="submit">Submit</button>
</form>

<!-- File uploads -->
<form name="file-upload" method="POST" data-netlify="true" enctype="multipart/form-data">
  <input type="file" name="file" />
  <button type="submit">Upload</button>
</form>
html
<!-- 使用蜜罐字段过滤垃圾信息 -->
<form name="contact" method="POST" data-netlify="true" data-netlify-honeypot="bot-field">
  <input type="hidden" name="form-name" value="contact" />
  <p class="hidden">
    <label>请不要填写此字段: <input name="bot-field" /></label>
  </p>
  <!-- 表单字段 -->
</form>

<!-- reCAPTCHA v2 -->
<form name="contact" method="POST" data-netlify="true" data-netlify-recaptcha="true">
  <div data-netlify-recaptcha="true"></div>
  <button type="submit">提交</button>
</form>

<!-- 文件上传 -->
<form name="file-upload" method="POST" data-netlify="true" enctype="multipart/form-data">
  <input type="file" name="file" />
  <button type="submit">上传</button>
</form>

Form Notifications

表单通知

toml
undefined
toml
undefined

netlify.toml

netlify.toml

[[plugins]] package = "@netlify/plugin-emails"
[plugins.inputs] formName = "contact" to = "admin@example.com" subject = "New contact form submission"
undefined
[[plugins]] package = "@netlify/plugin-emails"
[plugins.inputs] formName = "contact" to = "admin@example.com" subject = "新的联系表单提交"
undefined

Netlify Identity

Netlify 身份验证

Enable Identity

启用身份验证

javascript
// Add to HTML
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>

// Initialize
if (window.netlifyIdentity) {
  window.netlifyIdentity.on('init', user => {
    if (!user) {
      window.netlifyIdentity.on('login', () => {
        document.location.href = '/admin/';
      });
    }
  });
}
javascript
<!-- 添加到HTML-->
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>

<!-- 初始化 -->
if (window.netlifyIdentity) {
  window.netlifyIdentity.on('init', user => {
    if (!user) {
      window.netlifyIdentity.on('login', () => {
        document.location.href = '/admin/';
      });
    }
  });
}

React Integration

React 集成

jsx
// useNetlifyIdentity.js
import { useEffect, useState } from 'react';

export function useNetlifyIdentity() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const netlifyIdentity = window.netlifyIdentity;

    netlifyIdentity.on('init', user => setUser(user));
    netlifyIdentity.on('login', user => setUser(user));
    netlifyIdentity.on('logout', () => setUser(null));

    netlifyIdentity.init();
  }, []);

  return {
    user,
    login: () => window.netlifyIdentity.open('login'),
    logout: () => window.netlifyIdentity.logout(),
    signup: () => window.netlifyIdentity.open('signup'),
  };
}
jsx
// useNetlifyIdentity.js
import { useEffect, useState } from 'react';

export function useNetlifyIdentity() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const netlifyIdentity = window.netlifyIdentity;

    netlifyIdentity.on('init', user => setUser(user));
    netlifyIdentity.on('login', user => setUser(user));
    netlifyIdentity.on('logout', () => setUser(null));

    netlifyIdentity.init();
  }, []);

  return {
    user,
    login: () => window.netlifyIdentity.open('login'),
    logout: () => window.netlifyIdentity.logout(),
    signup: () => window.netlifyIdentity.open('signup'),
  };
}

Protected Functions

受保护的函数

javascript
// netlify/functions/protected.js
exports.handler = async (event, context) => {
  const { user } = context.clientContext;

  if (!user) {
    return {
      statusCode: 401,
      body: 'Unauthorized',
    };
  }

  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Protected data',
      user: user.email,
    }),
  };
};
javascript
// netlify/functions/protected.js
exports.handler = async (event, context) => {
  const { user } = context.clientContext;

  if (!user) {
    return {
      statusCode: 401,
      body: '未授权',
    };
  }

  return {
    statusCode: 200,
    body: JSON.stringify({
      message: '受保护的数据',
      user: user.email,
    }),
  };
};

Redirects and Rewrites

重定向与重写

_redirects File

_redirects 文件

text
undefined
text
undefined

_redirects file in publish directory

发布目录下的_redirects文件

Redirect with status code

带状态码的重定向

/old-path /new-path 301
/old-path /new-path 301

Rewrite (proxy)

重写(代理)

SPA fallback

SPA 回退

/* /index.html 200
/* /index.html 200

Force HTTPS

强制HTTPS

Conditional redirects

条件重定向

/news/* /blog/:splat 302 Country=us
/news/* /blog/:splat 302 Country=us

Role-based redirects

基于角色的重定向

/admin/* /admin/dashboard 200! Role=admin /admin/* /unauthorized 401
undefined
/admin/* /admin/dashboard 200! Role=admin /admin/* /unauthorized 401
undefined

netlify.toml Redirects

netlify.toml 重定向

toml
[[redirects]]
  from = "/old-path"
  to = "/new-path"
  status = 301

[[redirects]]
  from = "/api/*"
  to = "https://api.example.com/:splat"
  status = 200
  force = true

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

[[redirects]]
  from = "/admin/*"
  to = "/admin/dashboard"
  status = 200
  conditions = {Role = ["admin"]}
toml
[[redirects]]
  from = "/old-path"
  to = "/new-path"
  status = 301

[[redirects]]
  from = "/api/*"
  to = "https://api.example.com/:splat"
  status = 200
  force = true

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

[[redirects]]
  from = "/admin/*"
  to = "/admin/dashboard"
  status = 200
  conditions = {Role = ["admin"]}

Proxy with headers

带请求头的代理

[[redirects]] from = "/proxy/*" to = "https://backend.com/:splat" status = 200 force = true [redirects.headers] X-From = "Netlify"
undefined
[[redirects]] from = "/proxy/*" to = "https://backend.com/:splat" status = 200 force = true [redirects.headers] X-From = "Netlify"
undefined

Custom Headers

自定义请求头

toml
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    Content-Security-Policy = "default-src 'self'"

[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"
toml
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    Content-Security-Policy = "default-src 'self'"

[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

Deploy Previews

部署预览

Automatic Preview URLs

自动预览URL

toml
undefined
toml
undefined

netlify.toml

netlify.toml

[context.deploy-preview] command = "npm run build:preview"
[context.deploy-preview.environment] NODE_ENV = "preview" API_URL = "https://api-staging.example.com"
undefined
[context.deploy-preview] command = "npm run build:preview"
[context.deploy-preview.environment] NODE_ENV = "preview" API_URL = "https://api-staging.example.com"
undefined

Branch Deploys

分支部署

toml
undefined
toml
undefined

Deploy specific branches

部署特定分支

[context.staging] command = "npm run build:staging"
[context.staging.environment] API_URL = "https://api-staging.example.com"
[context.staging] command = "npm run build:staging"
[context.staging.environment] API_URL = "https://api-staging.example.com"

Branch pattern matching

分支模式匹配

[context.branch-deploy] command = "npm run build"
undefined
[context.branch-deploy] command = "npm run build"
undefined

Deploy Notifications

部署通知

bash
undefined
bash
undefined

GitHub PR comments

GitHub PR评论

Slack notifications

Slack通知

Email notifications

邮件通知

Configured in Netlify UI

在Netlify UI中配置

undefined
undefined

Split Testing (A/B Testing)

拆分测试(A/B测试)

Configuration

配置

toml
undefined
toml
undefined

netlify.toml

netlify.toml

[[redirects]] from = "/*" to = "/version-a/:splat" status = 200 conditions = {Cookie = ["ab_test=a"]} force = true
[[redirects]] from = "/*" to = "/version-b/:splat" status = 200 conditions = {Cookie = ["ab_test=b"]} force = true
[[redirects]] from = "/*" to = "/version-a/:splat" status = 200 conditions = {Cookie = ["ab_test=a"]} force = true
[[redirects]] from = "/*" to = "/version-b/:splat" status = 200 conditions = {Cookie = ["ab_test=b"]} force = true

50/50 split

50/50 拆分

[[redirects]] from = "/*" to = "/version-a/:splat" status = 200! percentage = 50
[[redirects]] from = "/*" to = "/version-b/:splat" status = 200!
undefined
[[redirects]] from = "/*" to = "/version-a/:splat" status = 200! percentage = 50
[[redirects]] from = "/*" to = "/version-b/:splat" status = 200!
undefined

Edge Functions

Edge Functions

Deno Runtime

Deno 运行时

typescript
// netlify/edge-functions/hello.ts
import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => {
  const url = new URL(request.url);

  return new Response(`Hello from ${url.pathname}`, {
    headers: { "content-type": "text/html" },
  });
};

export const config = { path: "/hello" };
typescript
// netlify/edge-functions/hello.ts
import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => {
  const url = new URL(request.url);

  return new Response(`Hello from ${url.pathname}`, {
    headers: { "content-type": "text/html" },
  });
};

export const config = { path: "/hello" };

Geolocation

地理位置

typescript
// netlify/edge-functions/geo.ts
import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => {
  const { city, country } = context.geo;

  return Response.json({
    location: `${city}, ${country}`,
  });
};
typescript
// netlify/edge-functions/geo.ts
import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => {
  const { city, country } = context.geo;

  return Response.json({
    location: `${city}, ${country}`,
  });
};

Transform Response

响应转换

typescript
// netlify/edge-functions/transform.ts
import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => {
  const response = await context.next();
  const text = await response.text();

  // Modify HTML
  const modified = text.replace(
    '</body>',
    '<script>console.log("Injected by edge");</script></body>'
  );

  return new Response(modified, response);
};

export const config = { path: "/*" };
typescript
// netlify/edge-functions/transform.ts
import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => {
  const response = await context.next();
  const text = await response.text();

  // 修改HTML
  const modified = text.replace(
    '</body>',
    '<script>console.log("由Edge函数注入");</script></body>'
  );

  return new Response(modified, response);
};

export const config = { path: "/*" };

Custom Domains and SSL

自定义域名与SSL

Add Custom Domain

添加自定义域名

bash
undefined
bash
undefined

Via CLI

通过CLI添加

netlify domains:add example.com
netlify domains:add example.com

DNS Configuration

DNS配置

A record: 75.2.60.5

A记录: 75.2.60.5

CNAME: <site-name>.netlify.app

CNAME: <site-name>.netlify.app

Verify domain

验证域名

netlify domains:verify example.com
undefined
netlify domains:verify example.com
undefined

SSL Certificates

SSL证书

toml
undefined
toml
undefined

Automatic HTTPS (default)

自动HTTPS(默认开启)

Free Let's Encrypt certificates

免费的Let's Encrypt证书

Auto-renewal

自动续期

Force HTTPS redirect

强制HTTPS重定向

[[redirects]] from = "http://example.com/*" to = "https://example.com/:splat" status = 301 force = true
undefined
[[redirects]] from = "http://example.com/*" to = "https://example.com/:splat" status = 301 force = true
undefined

Analytics

分析功能

Netlify Analytics

Netlify 分析

html
<!-- Automatically injected, no code needed -->
<!-- Server-side analytics, no client-side JS -->
html
<!-- 自动注入,无需额外代码 -->
<!-- 服务端分析,无需客户端JS -->

Custom Analytics

自定义分析

javascript
// Track custom events
function trackEvent(eventName, data) {
  fetch('/.netlify/functions/analytics', {
    method: 'POST',
    body: JSON.stringify({ event: eventName, ...data }),
  });
}

trackEvent('button_click', { button: 'signup' });
javascript
// 跟踪自定义事件
function trackEvent(eventName, data) {
  fetch('/.netlify/functions/analytics', {
    method: 'POST',
    body: JSON.stringify({ event: eventName, ...data }),
  });
}

trackEvent('button_click', { button: 'signup' });

CLI Advanced Usage

CLI 高级用法

Development Server

开发服务器

bash
undefined
bash
undefined

Run functions locally

本地运行函数

netlify dev
netlify dev

Specific port

指定端口

netlify dev --port 3000
netlify dev --port 3000

Live session sharing

实时会话共享

netlify dev --live
netlify dev --live

Functions only

仅运行函数

netlify functions:serve
undefined
netlify functions:serve
undefined

Site Management

站点管理

bash
undefined
bash
undefined

Link existing site

关联已有站点

netlify link
netlify link

Create new site

创建新站点

netlify sites:create
netlify sites:create

List sites

列出所有站点

netlify sites:list
netlify sites:list

Site info

站点信息

netlify status
netlify status

Open site in browser

在浏览器中打开站点

netlify open
undefined
netlify open
undefined

Deploy Management

部署管理

bash
undefined
bash
undefined

List deploys

列出所有部署

netlify deploy:list
netlify deploy:list

Rollback to previous deploy

回滚到上一个部署版本

netlify rollback
netlify rollback

Cancel deploy

取消部署

netlify deploy:cancel <deploy-id>
undefined
netlify deploy:cancel <deploy-id>
undefined

Git Integration

Git 集成

Continuous Deployment

持续部署

toml
undefined
toml
undefined

netlify.toml

netlify.toml

[build] command = "npm run build" publish = "dist"
[build] command = "npm run build" publish = "dist"

Auto-publish on Git push

Git推送时自动发布

Production: main/master branch

生产环境:main/master分支

Previews: all pull requests

预览环境:所有拉取请求

Branch deploys: configured branches

分支部署:已配置的分支

undefined
undefined

Deploy Hooks

部署钩子

bash
undefined
bash
undefined

Trigger builds via webhook

通过Webhook触发构建

curl -X POST -d {} https://api.netlify.com/build_hooks/<hook-id>
curl -X POST -d {} https://api.netlify.com/build_hooks/<hook-id>

Scheduled builds (use external cron + webhook)

定时构建(使用外部定时任务 + Webhook)

undefined
undefined

Best Practices

最佳实践

Performance Optimization

性能优化

toml
undefined
toml
undefined

Enable processing

启用处理

[build.processing] skip_processing = false
[build.processing.css] bundle = true minify = true
[build.processing.js] bundle = true minify = true
[build.processing.images] compress = true
[build.processing] skip_processing = false
[build.processing.css] bundle = true minify = true
[build.processing.js] bundle = true minify = true
[build.processing.images] compress = true

Asset optimization

资源优化

[[headers]] for = "/assets/*" [headers.values] Cache-Control = "public, max-age=31536000, immutable"
undefined
[[headers]] for = "/assets/*" [headers.values] Cache-Control = "public, max-age=31536000, immutable"
undefined

Security Headers

安全请求头

toml
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
    X-XSS-Protection = "1; mode=block"
    Referrer-Policy = "strict-origin-when-cross-origin"
    Permissions-Policy = "geolocation=(), microphone=(), camera=()"
    Content-Security-Policy = """
      default-src 'self';
      script-src 'self' 'unsafe-inline';
      style-src 'self' 'unsafe-inline';
      img-src 'self' data: https:;
      font-src 'self' data:;
    """
toml
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
    X-XSS-Protection = "1; mode=block"
    Referrer-Policy = "strict-origin-when-cross-origin"
    Permissions-Policy = "geolocation=(), microphone=(), camera=()"
    Content-Security-Policy = """
      default-src 'self';
      script-src 'self' 'unsafe-inline';
      style-src 'self' 'unsafe-inline';
      img-src 'self' data: https:;
      font-src 'self' data:;
    """

Function Best Practices

函数最佳实践

javascript
// Keep functions lightweight
// Use connection pooling
// Cache external API responses
// Set appropriate timeouts
// Handle errors gracefully

exports.handler = async (event) => {
  try {
    // Set timeout
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 8000);

    const response = await fetch(API_URL, {
      signal: controller.signal,
    });

    clearTimeout(timeout);

    return {
      statusCode: 200,
      body: JSON.stringify(await response.json()),
    };
  } catch (error) {
    console.error('Function error:', error);

    return {
      statusCode: 500,
      body: JSON.stringify({ error: 'Internal server error' }),
    };
  }
};
javascript
// 保持函数轻量化
// 使用连接池
// 缓存外部API响应
// 设置合适的超时时间
// 优雅处理错误

exports.handler = async (event) => {
  try {
    // 设置超时
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 8000);

    const response = await fetch(API_URL, {
      signal: controller.signal,
    });

    clearTimeout(timeout);

    return {
      statusCode: 200,
      body: JSON.stringify(await response.json()),
    };
  } catch (error) {
    console.error('函数错误:', error);

    return {
      statusCode: 500,
      body: JSON.stringify({ error: '内部服务器错误' }),
    };
  }
};

Build Optimization

构建优化

toml
[build]
  command = "npm run build"
  publish = "dist"

  # Skip builds when not needed
  ignore = """
    git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF -- . ':(exclude)docs/' ':(exclude)*.md'
  """
toml
[build]
  command = "npm run build"
  publish = "dist"

  # 无需构建时跳过
  ignore = """
    git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF -- . ':(exclude)docs/' ':(exclude)*.md'
  """

Cache dependencies

缓存依赖

[build.environment] NPM_FLAGS = "--legacy-peer-deps" NODE_OPTIONS = "--max-old-space-size=4096"
undefined
[build.environment] NPM_FLAGS = "--legacy-peer-deps" NODE_OPTIONS = "--max-old-space-size=4096"
undefined

Monorepo Support

单仓库多项目(Monorepo)支持

toml
undefined
toml
undefined

netlify.toml

netlify.toml

[build] base = "packages/web" command = "npm run build" publish = "dist"

Only build when package changes

ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/web"
undefined
[build] base = "packages/web" command = "npm run build" publish = "dist"

仅当包变更时构建

ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/web"
undefined

Common Patterns

常见模式

SPA with API Proxy

带API代理的SPA

toml
[build]
  command = "npm run build"
  publish = "build"
  functions = "netlify/functions"

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

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200
toml
[build]
  command = "npm run build"
  publish = "build"
  functions = "netlify/functions"

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

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

Microsite with Subfolder

子目录微站点

toml
[[redirects]]
  from = "/blog/*"
  to = "https://blog.example.com/:splat"
  status = 200
  force = true
toml
[[redirects]]
  from = "/blog/*"
  to = "https://blog.example.com/:splat"
  status = 200
  force = true

Authentication Gateway

身份验证网关

toml
[[redirects]]
  from = "/app/*"
  to = "/app/dashboard"
  status = 200
  conditions = {Role = ["user"]}

[[redirects]]
  from = "/app/*"
  to = "/login"
  status = 302

Summary: Netlify provides a complete JAMstack platform with static hosting, serverless functions, forms, and identity management. Key strengths include atomic deploys, instant cache invalidation, deploy previews, and built-in CDN. Configure via netlify.toml for builds, redirects, headers, and environment-specific settings. Leverage serverless functions for backend logic, forms for user input, and Edge Functions for edge computing. Best practices include performance optimization, security headers, and efficient build configurations.
toml
[[redirects]]
  from = "/app/*"
  to = "/app/dashboard"
  status = 200
  conditions = {Role = ["user"]}

[[redirects]]
  from = "/app/*"
  to = "/login"
  status = 302

总结: Netlify 提供了完整的JAMstack平台,包含静态托管、无服务器函数、表单和身份验证管理。其核心优势包括原子化部署、即时缓存失效、部署预览和内置CDN。可通过netlify.toml配置构建、重定向、请求头和环境特定设置。利用无服务器函数实现后端逻辑,表单处理用户输入,Edge Functions实现边缘计算。最佳实践包括性能优化、安全请求头和高效的构建配置。