第7章 7.4 部署:Vercel / Netlify / Nginx

(本文是「Vue3 从入门到精通」系列第 34 章,承接上一章「7.3 Monorepo:pnpm workspace」,建议先阅读上一章再继续)

上一章我们学会了用 pnpm workspace 管理 Monorepo 项目,多个子项目可以共享依赖、互相引用,终于不用一个项目装一遍 node_modules 了。但是代码写完了,总不能一直跑在本地吧?你得把它部署到服务器上,让全世界的人都能访问你的网站。

这一章我们不写 Vue 代码,换换口味——用 Python 写一个「部署配置生成器」,帮你一键生成 Vercel、Netlify、Nginx 的配置文件。你不需要懂 Vue,也不需要装 Node,光靠这个 Python 脚本,以后每次新建项目都能自动生成对应的部署配置,省时省力。

学完这章,你就能:
- 用 Python 读写 JSON/YAML 配置文件
- 自动生成 Vercel 的 vercel.json
- 自动生成 Netlify 的 _redirects\n\n![Simple tech illustration expla](https://blog.xxyye.com/wp-content/uploads/2026/06/75b8098a451be6d.png)\n\n![AI comic creation scene, creat](https://blog.xxyye.com/wp-content/uploads/2026/06/07c14da9b9eba0a.png)\n\n
- 自动生成 Nginx 的 nginx.conf


🎯 开场 3 分钟:为什么要学这个?

真实场景

假设你刚用 Vue3 + Vite 写完一个组件库,准备发布到 npm。在本地跑得好好的,但当你试图:
1. 部署到 Vercel 时,不知道该配什么构建命令
2. 部署到 Netlify 时,重定向规则老写错
3. 部署到自己的服务器时,Nginx 配置看着像天书

每个平台配置格式都不一样,查文档查到头秃。

痛点

  • 配置格式不统一:Vercel 用 JSON、Netlify 用纯文本重定向规则、Nginx 有自己的语法
  • 容易写错:一个分号、一个斜杠错了,网站就 404
  • 重复劳动:每个新项目都要重新配一遍

解决什么问题

用 Python 写一个配置文件生成器,你告诉它「我要部署到 Vercel」,它就给你生成好能用的 vercel.json。以后新建项目,跑一下脚本,配置文件全自动生成。


🧱 基础 25 分钟:核心概念

什么是配置文件?

生活类比:你去餐厅吃饭,菜单就是「配置文件」——上面写了有什么菜、价格多少、忌口要提前说。厨房(程序)照着菜单做菜,不会乱来。

为什么要用:项目大了,配置项可能十几个甚至几十个。硬编码在代码里,改一个要改好几处;用配置文件,改一处全生效。

Python 里怎么用

import json

# 模拟 vercel.json 配置文件
vercel_config = {
"buildCommand": "npm run build",
"outputDirectory": "dist",
"framework": "vite"
}

# 写入文件
with open("vercel.json", "w", encoding="utf-8") as f:
json.dump(vercel_config, f, indent=2)

print("配置文件生成成功!")

运行结果:

配置文件生成成功!

json.dump() 把字典转成 JSON 字符串,写入文件。相当于把「点菜单」写成纸质文件保存下来。


什么是 YAML 格式?

YAML 是一种比 JSON 更易读的配置文件格式,Netlify 和很多 CI/CD 工具喜欢用它。

生活类比:JSON 像「正式合同」,每条规则都要用引号、逗号、括号框起来;YAML 像「便签纸」,能用缩进表示层级,更像 human 自然语言。

为什么要用:Nginx 的配置、GitHub Actions 的 workflow,都用 YAML。学会读/写 YAML,能搞定一半运维配置。

Python 里怎么用(需要安装 pyyaml):

# 先 pip install pyyaml
import yaml

# 模拟 Nginx 配置文件(YAML 格式)
nginx_config = {
"server": {
    "listen": 80,
    "server_name": "example.com",
    "locations": [
        {"path": "/", "proxy_pass": "http://localhost:3000"},
        {"path": "/api", "proxy_pass": "http://localhost:8000"}
    ]
}
}

# 写入文件
with open("nginx.yaml", "w", encoding="utf-8") as f:
yaml.dump(nginx_config, f, allow_unicode=True, default_flow_style=False)

print("Nginx 配置生成成功!")

运行结果:

Nginx 配置生成成功!

yaml.dump() 把字典转成 YAML 格式。default_flow_style=False 让输出更易读(不用强行压成一行)。


什么是字符串模板?

生成配置文件时,内容大部分是固定的,只有少部分需要变化。字符串模板就是「填空题」——先写好固定部分,用占位符标记需要填的地方。

生活类比:结婚请帖模板——「恭请 [姓名] 出席婚礼」,方括号就是占位符,填上具体人名就成了一张真请帖。

Python 里怎么用

# 方式1:f-string(简单场景)
name = "小明"
age = 25
print(f"{name} 今年 {age} 岁")

# 方式2:str.format()(复杂模板)
template = "网站域名:{domain},端口:{port},是否启用SSL:{ssl}"
config = template.format(domain="example.com", port=443, ssl=True)
print(config)

运行结果:

小明 今年 25 岁
网站域名:example.com,端口:443,是否启用SSL:True

f-string{} 包裹变量名,适合简单替换。str.format() 适合大段模板。


什么是命令行参数?

你的 Python 脚本可能会给不同人用,每个人想要的配置不一样。命令行参数让用户跑脚本时指定「我要部署到哪个平台」「域名是什么」,不用改代码。

生活类比:自助取票机让你选「起点站」「终点站」,不同人取不同票,但机器是同一台。

Python 里怎么用

import sys

# sys.argv 是命令行参数列表
# python deploy.py vercel example.com
# sys.argv = ["deploy.py", "vercel", "example.com"]

if len(sys.argv) < 3:
print("用法:python deploy.py <平台> <域名>")
print("例如:python deploy.py vercel mysite.com")
sys.exit(1)

platform = sys.argv[1]
domain = sys.argv[2]

print(f"准备为 {platform} 生成配置,域名为 {domain}")

运行:

python deploy.py netlify mysite.netlify.app

输出:

准备为 netlify 生成配置,域名为 mysite.netlify.app

sys.argv[0] 是脚本名,sys.argv[1] 是第一个参数,以此类推。


什么是文件读写?

生成配置后要写入文件,用户才能拿去用。读文件和写文件是最基础的操作。

生活类比:写配置文件就像「写信」——写信(写文件)是把脑子里的想法变成纸上的字,读信(读文件)是把纸上的字变回脑子里的想法。

Python 里怎么用

# 读取已有配置文件
with open("vercel.json", "r", encoding="utf-8") as f:
content = f.read()
print("文件内容:", content)

# 写入新配置文件
config_text = '{"version": 2, "buildCommand": "npm run build"}'
with open("output.json", "w", encoding="utf-8") as f:
f.write(config_text)

print("写入完成!")

运行结果:

文件内容: {"buildCommand": "npm run build", "framework": "vite", "outputDirectory": "dist"}
写入完成!

open() 的第二个参数 "r" 表示读(read),"w" 表示写(write,会覆盖原文件)。


🔥 实战 35 分钟:3 个递进的小项目

项目 1(5 分钟):生成 Vercel 配置文件

目标:输入项目信息,生成一个可用的 vercel.json

完整代码

import json
import sys


def generate_vercel_config(project_name, build_command="npm run build", output_dir="dist"):
"""生成 Vercel 配置文件"""
config = {
    "projectName": project_name,
    "buildCommand": build_command,
    "outputDirectory": output_dir,
    "framework": None,  # None 表示自动检测
    "rewrites": [
        {"source": "/(.*)", "destination": "/index.html"}
    ]
}
return config


def save_vercel_json(config, filename="vercel.json"):
"""保存配置到文件"""
with open(filename, "w", encoding="utf-8") as f:
    json.dump(config, f, indent=2, ensure_ascii=False)
print(f"✅ 已生成 {filename}")


if __name__ == "__main__":
# 模拟命令行参数
project_name = sys.argv[1] if len(sys.argv) > 1 else "my-vue-app"

config = generate_vercel_config(project_name)
save_vercel_json(config)

print("\n生成的配置内容:")
print(json.dumps(config, indent=2, ensure_ascii=False))

运行

python deploy_vercel.py my-component-lib

预期输出

✅ 已生成 vercel.json

生成的配置内容:
{
"projectName": "my-component-lib",
"buildCommand": "npm run build",
"outputDirectory": "dist",
"framework": null,
"rewrites": [
{
  "source": "/(.*)",
  "destination": "/index.html"
}
]
}

解释:这个脚本生成了一个 Vercel 配置,包含 SPA 路由重写规则——所有路径都回退到 index.html,解决 Vue Router 的 History 模式 404 问题。


项目 2(15 分钟):生成 Netlify 配置文件(含重定向规则)

目标:读取一个 CSV 文件(包含重定向规则),生成 Netlify 的 _redirects 文件。

准备一个 CSV 文件 redirects.csv

from,to,status
/,/home,301
/login,/auth,302
/dashboard,/app/dashboard,200

完整代码

import csv
import sys


def read_redirects_from_csv(csv_file):
"""从 CSV 读取重定向规则"""
redirects = []
with open(csv_file, "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        redirects.append({
            "from": row["from"],
            "to": row["to"],
            "status": int(row["status"])
        })
return redirects


def generate_netlify_redirects(redirects):
"""生成 Netlify _redirects 文件内容"""
lines = []
for rule in redirects:
    status_part = f"={rule['status']}" if rule["status"] != 200 else ""
    line = f"{rule['from']} {rule['to']}{status_part}"
    lines.append(line)
return "\n".join(lines) + "\n"


def save_redirects_file(content, filename="_redirects"):
"""保存重定向文件"""
with open(filename, "w", encoding="utf-8") as f:
    f.write(content)
print(f"✅ 已生成 {filename}")


def show_preview(content):
"""显示文件预览"""
print("\n📄 文件内容预览:")
print("-" * 40)
print(content)
print("-" * 40)


if __name__ == "__main__":
csv_file = sys.argv[1] if len(sys.argv) > 1 else "redirects.csv"

print(f"📖 读取 CSV 文件:{csv_file}")
redirects = read_redirects_from_csv(csv_file)
print(f"📊 读取到 {len(redirects)} 条重定向规则")

content = generate_netlify_redirects(redirects)
save_redirects_file(content)
show_preview(content)

预期输出

📖 读取 CSV 文件:redirects.csv
📊 读取到 3 条重定向规则
✅ 已生成 _redirects

📄 文件内容预览:
----------------------------------------
/  /home  =301
/login  /auth  =302
/dashboard  /app/dashboard
----------------------------------------

解释:Netlify 的 _redirects 语法和 Nginx 不一样——用空格分隔,状态码用 =<code> 后缀。200 表示 rewrite(不改 URL),301/302 表示跳转。


项目 3(15 分钟):一个完整的「部署配置生成器」

目标:综合前两个项目,写一个命令行工具,输入 python deploy.py vercel mysite.com 就生成对应平台的配置文件。

完整代码

#!/usr/bin/env python3
"""
部署配置生成器
支持 Vercel / Netlify / Nginx 配置文件自动生成
"""

import json
import yaml
import csv
import os
import sys


def generate_vercel(project_name, build_command, output_dir, domain):
"""生成 Vercel 配置"""
config = {
    "projectName": project_name,
    "buildCommand": build_command,
    "outputDirectory": output_dir,
    "installCommand": "npm install",
    "framework": None,
    "rewrites": [
        {"source": "/(.*)", "destination": "/index.html"}
    ],
    "redirects": [
        {
            "source": "/api/(.*)",
            "destination": f"https://{domain}/api/$1",
            "permanent": False
        }
    ]
}
return config


def generate_netlify_redirects_from_csv(csv_file):
"""从 CSV 生成 Netlify 重定向规则"""
redirects = []
with open(csv_file, "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        status = row.get("status", "200")
        status_part = f"={status}" if status != "200" else ""
        redirects.append(f"{row['from']}  {row['to']}{status_part}")
return "\n".join(redirects) + "\n"


def generate_nginx_config(domain, port, vue_port):
"""生成 Nginx 配置"""
config = {
    "server": {
        "listen": port,
        "server_name": domain,
        "root": "/var/www/html",
        "index": ["index.html"],
        "locations": {
            "/": {
                "try_files": ["$uri", "$uri/", "/index.html"]
            },
            "/api/": {
                "proxy_pass": f"http://localhost:{vue_port}/",
                "proxy_set_header": {
                    "Host": "$host",
                    "X-Real-IP": "$remote_addr"
                }
            }
        }
    }
}
return config


def save_file(content, filename):
"""保存文件"""
with open(filename, "w", encoding="utf-8") as f:
    f.write(content)
print(f"  ✅ {filename}")


def main():
if len(sys.argv) < 3:
    print("用法:python deploy.py <平台> <域名> [参数...]")
    print("")
    print("平台选项:")
    print("  vercel   - 生成 vercel.json")
    print("  netlify  - 生成 _redirects(需要 redirects.csv)")
    print("  nginx    - 生成 nginx.conf")
    print("")
    print("示例:")
    print("  python deploy.py vercel mysite.com")
    print("  python deploy.py netlify mysite.netlify.app")
    print("  python deploy.py nginx example.com 80 3000")
    sys.exit(1)

platform = sys.argv[1].lower()
domain = sys.argv[2]

print(f"\n🚀 部署配置生成器")
print(f"   平台:{platform}")
print(f"   域名:{domain}")
print("-" * 40)

if platform == "vercel":
    build_cmd = sys.argv[3] if len(sys.argv) > 3 else "npm run build"
    output_dir = sys.argv[4] if len(sys.argv) > 4 else "dist"

    config = generate_vercel("my-project", build_cmd, output_dir, domain)
    content = json.dumps(config, indent=2, ensure_ascii=False)
    save_file(content, "vercel.json")
    print(f"\n📝 vercel.json 已生成,包含 SPA 路由重写规则")

elif platform == "netlify":
    csv_file = "redirects.csv"
    if not os.path.exists(csv_file):
        print(f"❌ 找不到 {csv_file},请先创建重定向规则文件")
        sys.exit(1)

    content = generate_netlify_redirects_from_csv(csv_file)
    save_file(content, "_redirects")
    print(f"\n📝 _redirects 已生成(从 {csv_file} 读取)")

elif platform == "nginx":
    port = int(sys.argv[3]) if len(sys.argv) > 3 else 80
    vue_port = int(sys.argv[4]) if len(sys.argv) > 4 else 3000

    config = generate_nginx_config(domain, port, vue_port)
    content = yaml.dump(config, allow_unicode=True, default_flow_style=False)
    save_file(content, "nginx.conf")
    print(f"\n📝 nginx.conf 已生成,监听 {port} 端口,API 代理到 {vue_port}")

else:
    print(f"❌ 不支持的平台:{platform}")
    sys.exit(1)

print("\n✨ 完成!将生成的配置文件放到项目根目录即可。\n")


if __name__ == "__main__":
main()

运行示例 1

python deploy.py vercel my-component-lib

预期输出

🚀 部署配置生成器
台:vercel
名:my-component-lib
----------------------------------------
✅ vercel.json

📝 vercel.json 已生成,包含 SPA 路由重写规则

✨ 完成!将生成的配置文件放到项目根目录即可。

运行示例 2

python deploy.py nginx example.com 8080 5173

预期输出

🚀 部署配置生成器
台:nginx
名:example.com
----------------------------------------
✅ nginx.conf

📝 nginx.conf 已生成,监听 8080 端口,API 代理到 5173

✨ 完成!将生成的配置文件放到项目根目录即可。

解释:这个脚本综合了前两个项目的功能,用 if/elif 判断平台,读取不同参数,生成不同格式的配置。学会了这种「主函数 + 子函数」的结构,你就能写任何命令行工具。


💪 进阶 20 分钟:常见坑 + 性能小贴士

坑 1:JSON 的引号必须是双引号

# ❌ 错误:Python 字符串用单引号,JSON 不认
json_str = "{'name': '小明'}"
json.loads(json_str)  # 报错!

# ✅ 正确:用双引号
json_str = '{"name": "小明"}'
data = json.loads(json_str)
print(data["name"])  # 输出:小明

原因:JSON 规范要求字符串必须用双引号,Python 的 json 模块会自动处理这个转换。


坑 2:YAML 缩进必须一致

# ❌ 错误:混用空格和 Tab,YAML 解析可能出错
config = {
"server": {
"listen": 80,    # 缩进不一致
    "name": "test"
}
}

# ✅ 正确:全部用 2 或 4 个空格
config = {
"server": {
    "listen": 80,
    "name": "test"
}
}

原因:YAML 用缩进表示层级,Tab 和空格混用会导致解析出莫名其妙的结果。


坑 3:读取文件路径要处理编码

# ❌ 错误:不指定编码,Windows 默认用 GBK 读UTF-8文件会乱码
with open("vercel.json", "r") as f:
content = f.read()  # 中文可能乱码

# ✅ 正确:明确指定 UTF-8
with open("vercel.json", "r", encoding="utf-8") as f:
content = f.read()  # 稳妥

原因:Windows 默认编码是 GBK,macOS 和 Linux 是 UTF-8。指定编码是最佳实践。


坑 4:命令行参数索引从 1 开始

# ❌ 错误:以为 sys.argv[0] 是第一个参数
script_name = sys.argv[1]  # 错!这是脚本自己

# ✅ 正确:sys.argv[0] 是脚本路径,参数从 1 开始
script_name = sys.argv[0]
first_arg = sys.argv[1]  # 才是第一个参数

原因sys.argv 列表的第一个元素永远是脚本文件名。


坑 5:写入文件前确认目录存在

# ❌ 错误:直接写文件,但目录不存在
with open("output/vercel.json", "w") as f:
f.write(content)  # 报错:目录不存在

# ✅ 正确:先创建目录
import os
os.makedirs("output", exist_ok=True)
with open("output/vercel.json", "w") as f:
f.write(content)  # 稳妥

原因open() 不会自动创建父目录,写入前要确保路径存在。


性能小贴士:批量写入用上下文管理器

# ✅ 好习惯:用 with 自动关闭文件
with open("vercel.json", "w", encoding="utf-8") as f:
json.dump(config, f, indent=2)

# 不用手动 f.close(),with 块结束自动关闭

原因:文件句柄是稀缺资源,用 with 确保及时释放。


调试技巧:print 大法

def generate_vercel_config(project_name):
print(f"[调试] 输入项目名:{project_name}")  # 打印中间值

config = {
    "projectName": project_name,
    "buildCommand": "npm run build"
}

print(f"[调试] 生成配置:{config}")  # 打印结果
return config

遇到问题先加 print,看看变量实际值是什么,比盯着代码猜快多了。


✏️ 练习题

练习 1(2 分钟):改平台名

项目 1 的代码,只改一个地方,让它生成的项目名变成 "awesome-ui"

  • 输入:运行 python deploy_vercel.py(不传参数)
  • 预期输出:"projectName": "awesome-ui"
  • 提示:找 sys.argv 那行,改默认值

练习 2(2 分钟):加一个条件判断

项目 1里,加一个 if 判断:如果 build_command"npm run build",就打印 "使用默认构建命令";否则打印 "使用自定义构建命令:xxx"

  • 输入:python deploy_vercel.py
  • 预期输出:包含 "使用默认构建命令" 的日志
  • 提示:在 generate_vercel_config 函数里加 if 判断

练习 3(3 分钟):处理新的 CSV

新建一个 routes.csv,包含 2 条规则:

from,to,status
/products,/shop,301
/about,/info,200

项目 2的方法处理这个新文件。

  • 输入:运行 python deploy_netlify.py routes.csv
  • 预期输出:生成包含 /products /shop =301_redirects 文件
  • 提示:改 sys.argv[1] 的默认值或传参

练习 4(3 分钟):串起两个项目

项目 2的 CSV 读取功能,集成到项目 3里——让 Vercel 模式也能读取 CSV 生成重定向规则。

  • 输入:运行 python deploy.py vercel myapp.com
  • 预期输出:vercel.json 里包含 redirects 数组
  • 提示:在 generate_vercel 函数里调用 CSV 读取函数

练习 5(5 分钟):分析报错

看下面这段代码的运行结果,为什么 config["user"] 取不到值?

import json

json_str = '{"name": "小明", "age": 25}'
config = json.loads(json_str)
print(config["user"])
  • 预期输出:报错 KeyError: 'user'
  • 提示:JSON 里的字段名和代码里写的要一致

作业:做一个「多环境配置文件生成器」

需求描述
开发项目通常有多个环境:开发(development)、测试(staging)、生产(production)。每个环境的 API 地址、调试开关都不一样。用 Python 写一个配置生成器,能根据环境生成对应的配置文件。

功能点
1. 支持 dev / staging / prod 三种环境
2. 每个环境有不同的 API_BASE_URLDEBUG 开关
3. 生成 JSON 格式的环境配置文件
4. 命令行传入环境名

加分项
1. 支持 -o 参数指定输出目录
2. 生成 .env.example 文件(列出所有可配置项)

验收标准
- 运行 python env_generator.py dev 生成 env.dev.json
- 运行 python env_generator.py prod -o ./config 生成 ./config/env.prod.json
- 文件内容包含 API_BASE_URLDEBUG 字段


📚 总结 + 资源

本文学到的 3 个核心点

  1. 配置文件是「菜单」:用 JSON/YAML 格式保存配置,程序读菜单干活,不把配置写死在代码里
  2. 字符串模板是「填空题」:用 f-stringformat() 把可变部分填进固定模板
  3. 命令行参数是「点菜」:用户跑脚本时告诉程序要什么,程序根据参数生成不同结果

延伸学习资源

  1. Python 官方文档 - json 模块:JSON 操作的完整指南
  2. PyYAML 官方文档:YAML 读写的更多用法
  3. Real Python - Command Line Apps:更深入的命令行参数处理(argparse)

互动钩子

你在部署 Vue 项目时遇到过什么坑?Vercel 的冷启动慢、Netlify 的重定向不生效、还是 Nginx 的跨域配置调崩了?评论区聊聊你的惨痛经历,老粉优先回复!


下一章我们要做一个综合实战:把前几章学的 Monorepo 管理、组件库开发、部署配置全部串起来,从零开始搭建一个可发布的 Vue3 组件库。敬请期待!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。