关于 netlify-config
netlify-config 是 Netlify 项目的配置参考技能,面向维护站点部署配置的开发者。它梳理配置文件优先级、重定向、响应头、函数及环境变量的规则与常见限制。
主要功能
- 01说明 netlify.toml、_redirects 与 _headers
- 02整理构建上下文及配置优先级
- 03讲解重定向、重写与代理规则
- 04涵盖函数和环境变量配置
- 05汇总密钥扫描与 Monorepo 注意事项
适用场景
- 01为站点添加 SPA 回退或代理重写
- 02排查构建上下文和配置覆盖问题
- 03配置函数运行时变量与密钥扫描
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ netlify/ context-and-tools --skill netlify-config安装后在 Claude Code 中输入/netlify-config确认已加载。
详细介绍
Netlify 配置
配置位于仓库根目录的三个文件中(对于 monorepo,则位于基础目录/包目录中):
netlify.toml— 构建、上下文、插件、函数、重定向、标头、开发。_redirects— 纯文本重定向/重写规则,保存到发布目录中,不带扩展名。_headers— 纯文本响应标头,保存到发布目录中。
发生冲突时,netlify.toml 中的值优先于 Netlify UI。netlify.toml 中的路径相对于基础目录(默认为根目录 /)使用绝对路径。
应优先使用的现代语法与旧语法
- 函数打包器:使用
node_bundler = "esbuild"。zisi是旧版 JS 默认值;TypeScript 始终使用esbuild。 - 临时重定向:使用
status = 302。不支持307。 - Gatsby Image CDN:使用
NETLIFY_IMAGE_CDN,不要使用已弃用的GATSBY_CLOUD_IMAGE_CDN。 - 将环境变量注入 TOML:不支持
key = "$VAR"(代理重定向中的signed除外)。请使用构建命令中的sed替换或构建插件(见下文)。
netlify.toml 构建与上下文
[build]
base = "frontend"
publish = "dist"
command = "npm run build"
environment = { NODE_VERSION = "18" }
[context.production]
publish = "output/"
command = "make publish"
[context.deploy-preview]
publish = "dist/"
[context."feat/branch"] # quote names with special characters
command = "npm run preview"
[build] 在 Bash 中运行。支持上下文的键包括 [build] 和 [[plugins]],但不包括 [[redirects]] 或 [[headers]](这些始终是全局的)。优先级从低到高:UI < toml < 任意上下文属性 < [context.<name>] < [context.branchname]。
重定向与重写
先处理 _redirects 规则,再处理 netlify.toml;在每个文件中,自上而下第一个匹配的规则生效——请将具体规则放在通用规则之前。边缘函数在重定向之前运行。
SPA history-pushState 回退(清洁 URL 所必需):
/* /index.html 200
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
_redirects 语法 — from to [status] [conditions],# 注释,路径区分大小写,特殊字符需进行 URL 编码:
/home / 301
/my-redirect / 302
/ecommerce /store-closed 404 # custom 404 for a path
/pass-through /index.html 200 # rewrite
/best-pets/dogs /best-pets/cats.html 200! # force/shadow (! or force=true)
/news/* /blog/:splat # splat
/news/:month/:date/:year/:slug /blog/:year/:month/:date/:slug # placeholders
/store id=:id /blog/:id 301 # query params
/ /anz 302 Country=au,nz # no spaces in value list
/israel/* /israel/he/:splat 302 Language=he
/* /legacy/:splat 200 Cookie=is_legacy,my_other_cookie
[[redirects]] 关键字:from、to、status(默认 301)、force(默认 false;!/覆盖规则)、query(query = {path = ":path"})、conditions({Language, Country, Role, Cookie})、headers(代理请求标头)、signed(签名代理使用的环境变量名称)。
注意事项:
- 不能通过重定向添加或移除末尾斜杠——CDN 会先规范化 URL;
/x/ → /x 301!规则会导致无限循环。请依赖 Pretty URLs(默认开启)。 - 星号通配符只能用于路径段的末尾(
/jobs/*),不能放在路径中间(/jobs/*.html无效)。占位符(:x)只能位于路径段开头;同一路径段中不能混用通配符和占位符。 - 不能从通配规则中排除某个路径;请将更具体的规则放在前面。
Country= ISO 3166-1 alpha-2;语言重定向仅匹配Accept-Language中的第一项。- 基于角色的重定向与外部身份验证提供方结合使用时仅适用于 Enterprise。
- 重定向达到 10,000 条或更多时,请使用通配符/占位符或边缘函数——序列化输出过大会导致部署失败。
代理
/api/* https://api.example.com/:splat 200
/netlify-site/* https://my-other-site.netlify.app/:splat 200 # use .netlify.app, not custom domain
[[redirects]] # custom request headers + force
from = "/search"
to = "https://api.mysearch.com"
status = 200
force = true
headers = {X-From = "Netlify"}
签名代理(signed 指定一个作用域为运行时的环境变量;必须位于 netlify.toml 中;JWS 仅适用于外部,不适用于 Netlify 到 Netlify):
[[redirects]]
from = "/search"
to = "https://api.mysearch.com"
status = 200
force = true
signed = "API_SIGNATURE_TOKEN_PLACEHOLDER"
**注意事项:**不允许跨团队重写;同一受密码保护的网站之间可以重写,但不能跨不同的受保护网站;代理超时时间为 26 s;默认只允许一跳;相对路径资源会失效(请使用绝对路径或 <base>);循环会被静默忽略。
自定义标头
/*
X-Frame-Options: DENY
/templates/index2.html
X-Frame-Options: SAMEORIGIN
多值:重复键(_headers),或使用多行 TOML 字符串:
[[headers]]
for = "/*"
[headers.values]
cache-control = '''
max-age=0,
no-cache,
no-store,
must-revalidate'''
注意事项:
_headers/netlify.toml中的标头是全局的,不会按分支/上下文限定。解决方法:移除全局标头,将标头文件保存在自定义目录中,并通过各上下文对应的构建命令,将它们cp到发布目录:[context.staging] command = "npm run build && cp ./custom-headers/_stagingHeaders ./dist/_headers"- 标头仅适用于来自 Netlify 存储的文件,不适用于代理内容或函数/边缘(SSR)响应;这些内容必须自行设置标头。
- 以下名称等会被忽略(由服务器设置):
Content-Length、Content-Encoding、Location(请使用重定向)、Set-Cookie、Server。 - 基本身份验证标头:仅限 Pro/Enterprise。跨子域 Cookie 需要自定义域名(
netlify.app位于 Public Suffix List 中)。
函数
[functions]
directory = "myfunctions/" # default: <base>/netlify/functions
node_bundler = "esbuild"
external_node_modules = ["package-1"] # esbuild only; native add-ons etc.
included_files = ["files/*.md"] # ! prefix excludes
[functions."api_*"] # glob/named blocks concatenate with top-level
external_node_modules = ["package-2"]
included_files = ["!files/post-1.md"]
环境变量
有两种存储方式:
- UI / CLI / API:存储在 Netlify 上(不在仓库中)。支持站点变量和共享变量、按上下文设置值、设置作用范围;可用于构建、函数/边缘/ODB、片段注入、表单和签名代理。任何敏感内容都建议使用此方式。
netlify.toml:存储在仓库中。仅支持站点变量、按上下文设置值,不支持选择作用范围(所有变量都会获得 Builds + Post processing 作用范围);仅可用于构建和片段注入。
netlify.toml 环境变量会覆盖同名的 UI/CLI/API 变量。
TOML 中按上下文设置值:
[context.production]
environment = { NODE_VERSION = "14.15.3" }
[context.deploy-preview.environment]
NOT_PRIVATE_ITEM = "not so secret"
[context.branch-deploy.environment]
NODE_ENV = "development"
CLI:
netlify env:set KEY value # --secret marks it a secret
netlify env:import .env # site vars; --replace-existing wipes others first
netlify env:unset KEY
netlify env:list --plain --context production > .env
netlify build # local build with Netlify's env vars
API:createEnvVars / updateEnvVar(is_secret: true)/ setEnvVarValue / deleteEnvVar / deleteEnvVarValue。
**访问语法:**在 build.command/ignore.command 中使用 Bash $VAR;在 Node 脚本和插件中使用 process.env.VAR。
作用范围(Pro/Enterprise;默认全部):Builds(站点构建)· Functions(Functions/Edge/ODB)· Runtime(表单、签名代理)· Post processing(片段注入)。共享变量仅限 Pro/Enterprise,且只有 Team Owner可以读取/编辑。站点变量和共享变量的键冲突时,优先级会按作用范围判定:站点变量仅在其实际涵盖的作用范围内优先。
**命名/限制:**键只能包含字母数字字符和下划线,且必须以字母开头(1KEY、_KEY1 无效);键最长为 255 个字符,值最长为 5,000 个字符。只读变量名为保留名称。更改后需要重新构建并部署。
通过保留的配置变量设置构建语言:NODE_VERSION、NPM_FLAGS、YARN_VERSION、BUN_VERSION、RUBY_VERSION、PHP_VERSION、PYTHON_VERSION、GO_VERSION、HUGO_VERSION、PNPM_FLAGS、NPM_TOKEN(Yarn:YARN_NPM_AUTH_TOKEN)等。
必须在 UI/CLI/API 中设置,不要在 netlify.toml 中设置(从仓库克隆后读取,或仅供运行时使用的变量):AWS_LAMBDA_JS_RUNTIME、GIT_LFS_ENABLED、GIT_LFS_FETCH_INCLUDE、NETLIFY_BUILD_DEBUG。
**CI 注意事项:**默认值为 true;如果导致构建失败,请在构建命令前加上 CI='' 。
将环境变量值注入标头/重定向
不支持 key = "$VAR"。仅支持路径(作用范围必须包含 Builds):
[build]
command = "sed -i \"s|HEADER_PLACEHOLDER|${PROD_API_LOCATION}|g\" netlify.toml && yarn build"
sed 替换仅适用于 [[headers]]/[[redirects]](在构建后读取),构建插件无法看到替换结果(插件会在构建命令前运行)。若要让插件能看到更改,请使用本地构建插件编辑 netlifyConfig。
常用只读构建变量
CONTEXT(production/deploy-preview/branch-deploy/dev)、BRANCH、COMMIT_REF、CACHED_COMMIT_REF、PULL_REQUEST、REVIEW_ID、URL、DEPLOY_URL、DEPLOY_PRIME_URL、SITE_ID、SITE_NAME。
密钥控制器
将变量标记为密钥:Contains secret values(UI)/ --secret(CLI)/ is_secret: true(API)。强制执行且不可自定义的策略:
- 密钥值为只写——设置后无法读取;不能移除标记来显示密钥。
- 密钥需要明确指定上下文和范围;不能带有
post processing范围。 - 只有在 Netlify 上运行的代码(edge/serverless/build)才能读取未遮蔽的值;Netlify 之外的环境只能看到遮蔽后的值。
dev上下文的值例外(可从 UI/CLI/API 读取未遮蔽值);netlify build永远不会输出原始值。
只要有任意变量被标记为密钥,密钥扫描就会自动运行(也会通过智能检测运行)。检测到密钥时会使构建失败,并记录其位置。通过按上下文设置的环境变量进行配置:
SECRETS_SCAN_ENABLED=false— 禁用所有扫描(失去所有密钥保护)。SECRETS_SCAN_SMART_DETECTION_ENABLED=false— 仅禁用智能检测。SECRETS_SCAN_OMIT_KEYS、SECRETS_SCAN_OMIT_PATHS(逗号分隔的列表;路径相对于仓库根目录,支持 glob)。SECRETS_SCAN_SMART_DETECTION_OMIT_VALUES— 将误报列入安全名单(优先使用此选项,而不是禁用扫描)。智能检测适用于 Personal/Pro/Enterprise。
扫描范围涵盖所有构建文件,扫描长度超过 4 个字符且非布尔值的内容,并搜索纯文本、base64 和 URI 编码形式。
敏感变量策略(仅限公开仓库)
此策略规定不受信任的部署(作者无法识别)能否获取敏感变量。站点成员发起的 Git 部署始终受信任,即使来自 fork 也如此。请在 Project configuration > Environment variables > Site policies 中设置:
- Require approval(默认)——不受信任的部署会等待成员批准。
- Deploy without sensitive variables ——运行构建,但不提供敏感变量。
- Deploy without restrictions ——提供所有变量。
GitHub Enterprise Server / GitLab self-managed 仓库不提供此功能(会被视为私有仓库)。
忽略构建
[build] 下的 ignore 用于决定是否重新构建——命令会在 Bash 中从基础目录运行(或使用固定的 Node.js 18;无法使用站点 package.json 中的依赖)。**退出码 1 = 有变更 → 继续构建;退出码 0 = 无变更 → 停止构建。**无论退出码如何,构建钩子都会始终触发构建。
[build]
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/blog-1 packages/common"
[build]
ignore = "node ignore_build.js" # separate file paths must start with ./
// ignore_build.js
process.exitCode = process.env.BRANCH.includes("debug") ? 0 : 1
Monorepo
将站点子目录设为包目录(将其 netlify.toml 保留在该目录中),基础目录保持为根目录 /,并在子目录级别声明依赖项。包目录只能在 UI 中设置,不能在 netlify.toml 中设置(Project configuration > Developer settings > Continuous deployment > Build settings)。配置文件的查找顺序:包目录 → 基础目录 → 根目录。netlify.toml 中的路径仍相对于基础目录,且必须使用绝对路径。netlify <cmd> --filter <site> 用于选择站点。
JavaScript 单页应用
构建命令为 npm run <script> / yarn <script>;发布目录通常为 dist(取决于框架)。添加 /* /index.html 200 回退规则(见上文),以支持 pushState 路由。采用代码拆分和哈希文件名的原子部署可能会因过时的引用而引发 Uncaught SyntaxError: Unexpected token——可禁用哈希文件名、使用永久链接或使用 Service Worker。
Netlify Dev [dev]
不会在 Bash 中运行(command 中不能使用 Bash 语法)。没有 environment 键——请在 [context.dev.environment] 下设置本地环境变量。
[dev]
command = "yarn start"
targetPort = 3000 # if both command + targetPort set, framework must be "#custom"
port = 8888
framework = "#custom"
[dev.https]
certFile = "cert.pem"
keyFile = "key.pem"
插件与扩展
[[plugins]]
package = "netlify-plugin-check-output-for-puppy-references"
[plugins.inputs]
breeds = ["pomeranian", "chihuahua"]
[[integrations]] # build-time extension; install on team first
name = "abc-performance-extension"
[integrations.config]
output_path = "reports/performance-reports.html"
完整参考页面:构建环境变量,网址为 https://docs.netlify.com/build/configure-builds/environment-variables.md;环境变量概览,网址为 https://docs.netlify.com/build/environment-variables/overview.md;Secrets Controller,网址为 https://docs.netlify.com/build/environment-variables/secrets-controller.md;重定向,网址为 https://docs.netlify.com/manage/routing/redirects/overview.md;重定向选项,网址为 https://docs.netlify.com/manage/routing/redirects/redirect-options.md;重写/代理,网址为 https://docs.netlify.com/manage/routing/redirects/rewrites-proxies.md;自定义标头,网址为 https://docs.netlify.com/manage/routing/headers.md;以及基于文件的配置,网址为 https://docs.netlify.com/build/configure-builds/file-based-configuration.md。
Netlify 内部规则(配置)
这些是组织约定,并非文档事实——由 ctx-gen 合并到渲染后的技能中,且不会自动生成。由技能维护者负责。
- 在
netlify.toml中设置的环境变量在运行时对函数或边缘函数不可用——在其中读取会返回undefined。请在 UI 中或使用netlify env:set设置运行时变量,不要在netlify.toml中设置。 - 切勿将机密放入客户端前缀环境变量(
VITE_、NEXT_PUBLIC_、PUBLIC_等)——这些变量会被内联到客户端包中;--secret无法保护它们。 - 在本地快照环境变量(
netlify env:list --plain > .env)时,请确保.env已加入 Git 忽略规则,切勿提交该文件。 - 明确说明环境变量作用范围之间的交互:作用范围为 Builds 的站点变量不会覆盖其他作用范围中的共享变量——优先级按各作用范围独立判定(仅在站点变量实际涵盖的作用范围内,站点变量优先于共享变量)。