评估静态部署时,只要项目的生产构建能生成一套完整且可独立访问的 HTML、CSS、JavaScript 和图片等文件,Vercel 与 Cloudflare Pages 均可作为候选。博客、文档和纯静态生成的 SPA,评估重点是构建可重复性、免费额度、预览协作和自定义域名工作流。若项目依赖 SSR、服务端 API、边缘函数、运行时重写或某个平台专用适配器,就不属于同一类静态站点的比较范围,不能直接套用静态站的免费额度替代对运行时环境的评估。
遇到本地成功而平台失败的情况,先按项目锁文件在本地执行生产构建,再从日志中定位第一个非零退出的命令及其前置错误上下文。构建结束后,检查配置目录是否确实包含入口 HTML 和静态资源;最后,将这组有效的构建配置完整迁移到另一个平台验证。这样可以分别排查源码、构建环境、产物上传和域名解析,避免盲目重装依赖造成环境混乱。
下面的命令只适用于以下 Node.js 项目:系统为 Linux 或 macOS,使用 package-lock.json 作为锁文件,并包含构建脚本。命令中的 <输出目录> 与脚本名必须按项目实际情况替换:
# Linux/macOS;含 package-lock.json 的 Node.js 项目
pwd
node --version
npm --version
npm ci
npm run build
find "<输出目录>" -maxdepth 2 -type f -print
如果项目使用的是其他包管理器,应按对应锁文件执行安装,不能为了尝试一次构建就随意更换包管理器。Node 版本也不能凭本地 shell 猜测,应该以项目声明、构建环境声明和日志中的实际版本为准。本文不提供示例构建日志或虚构的目录列表,真实结果必须从自己的仓库取得。
第一轮筛选可按站点形态收窄范围:
| 站点形态 | 先核对什么 | 初步判断 |
|---|---|---|
| 纯静态博客、文档 | 构建命令、输出目录、流量和存储口径 | 两边都可以作为候选,再比较当前额度和维护成本 |
| 预渲染的纯静态 SPA | 基础路径、客户端路由回退、静态资源路径 | 不能只看首页构建成功,还要验证直接访问子页面 |
| 需要 SSR、API 或边缘函数 | 运行时、函数能力、请求统计和计划条件 | 不属于本文的纯静态比较范围 |
| 频繁使用预览部署的团队项目 | 预览保留时间、并发构建、成员权限和环境变量隔离 | 需要单独核对团队计划与预览配额 |
| 有自定义域名、重定向或响应头要求 | DNS、代理、证书、缓存和平台配置边界 | 先确认当前官方能力,再决定迁移路径 |
比较速度前,先让两个平台使用同一份有效构建配置。仓库根目录、应用目录、构建工作目录和输出目录并不是同一个概念。仓库根目录通常是整个 checkout 的顶层,单体仓库里的应用可能位于某个子目录;本地进入应用目录执行构建,并不代表平台也会从那个目录开始。构建输出目录的相对路径也必须明确以哪个目录为基准,否则构建过程可能已经生成了文件,但部署阶段读取了另一个位置。
如果仓库使用 Git submodule,本地完整 clone 和平台构建时拿到的源码树可能不同。出现“本地有文件、平台提示找不到文件”时,先确认子模块是否包含在当前构建提交中,再检查依赖是否由包管理器在工作区根目录安装。不要把源码缺失误判成平台构建额度不足,也不要通过删除锁文件来掩盖工作目录或依赖安装方式不一致的问题。
排查时要区分框架自动识别与手动设置。平台可能根据框架类型填入默认的构建命令和输出目录,手动设置则可能覆盖这组默认值;框架自身的配置还可能影响资源前缀和部署子路径。排查时应记录最终生效的命令、工作目录和输出目录,并确保它们与 package.json 中的脚本、生成器配置以及静态目录结构一致。不要同时保留两套互相冲突的约定,否则本地看起来正常,平台却可能构建了另一份产物。
Node 版本、包管理器和锁文件应作为同一组条件核对。package.json 中的构建脚本、package-lock.json、pnpm-lock.yaml 或其他锁文件,以及平台的 Node 版本,可能组合出与本地不同的依赖树。安装依赖失败时,先看日志,确认问题出在依赖解析、下载、私有仓库、脚本还是工作目录;不要在第一轮就换包管理器或重新生成锁文件,否则排障条件也会改变。
环境变量需要按使用阶段分别核对。构建时变量可能影响生成的 HTML、文章内容、资源地址或主题配置;暴露给浏览器的变量会被打进前端代码,不能当作秘密保存;纯静态站点没有持续运行的服务端进程,不能指望部署完成后再读取服务器环境变量。修改变量后,需要重新构建和部署,再验证;不能用旧部署的结果判断新配置是否生效。
Git 自动部署、预览分支和生产分支需要分别核对。预览构建可能使用不同的变量、配置或默认设置,生产构建则可能启用另一套脚本。比较两条链路时,至少要核对提交版本、仓库根目录、构建命令、输出目录、Node 版本、包管理器、环境变量作用域和基础路径。若考虑命令行部署或直接上传,还要先查当前官方文档支持的入口、认证方式、忽略规则、目录限制以及是否会产生额外的构建或部署统计;没有核验资料时,不把某个上传命令写成通用答案。
配置对齐后,再比较免费额度。最容易混淆的是双方在构建次数、构建时长、并发限制、统计周期、请求量、流量、存储空间、单文件大小和文件数量上的统计口径,不能只比较“免费”二字。评估时,应按同一套标准逐项核对各平台的额度限制与计费状态。
| 核对项 | 接入当天需要记录的内容 | 容易混淆的地方 |
|---|---|---|
| 构建与部署 | 构建次数、部署次数、构建时长、并发限制、统计周期 | 构建成功次数不等于访问请求数,预览是否计入也要确认 |
| 访问与存储 | 请求量、流量或带宽、存储空间、单文件大小、文件数量 | 源码、构建产物、缓存和静态文件可能不是同一项统计 |
| 功能条件 | 自定义域名、预览环境、环境变量、函数能力、项目成员数量 | 功能可用不等于免费,也不等于没有并发或保留限制 |
| 统计对象 | 按账号、项目、站点归集,以及生产和预览是否分开 | 同一账号下多个项目的额度不能直接相加或横向推断 |
| 超限与重置 | 重置时间、硬性上限、公平使用、升级、限流或阻断行为 | 不同平台的超限表现不能互相类推 |
| 使用性质 | 个人项目、团队项目、商业用途、成员席位和公平使用条款 | 免费开发额度不等于自动获得商业使用许可 |
补录任何数字时,都应同时写明计划名称、适用条件、查询日期、官方文档标题或编号。只记录“每月多少请求”而不记录统计对象,仍可能得到错误结论。对于纯静态站点,构建频率通常比访客数更直接影响构建额度;静态资源流量、构建产物保留和项目存储又是不同问题。若项目误生成了函数或服务端路由,函数请求还可能进入另一套计费口径,评估时也需要脱离静态站的比较范围。
当前没有可核验的 Vercel 与 Cloudflare 官方产品资料,因此本文不填写具体免费额度数字、计划名称、菜单路径、配置开关、字段名、错误码或引用编号。直接排列未经核对的第三方文章中的套餐数字,会混淆不同统计周期、计划条件和超限行为。选型时,应在当天打开两家的官方定价、构建文档、函数文档和条款页面重新记录。
构建失败时,应从日志中的第一个失败命令追查根因,不能只看最后一句“部署失败”。本地成功但平台安装依赖失败,常见方向是锁文件没有进入构建提交、包管理器不一致、Node 版本不同、私有依赖源不可用、工作目录错误或子模块缺失。先确认平台实际在哪个目录执行了哪条安装命令,再决定是否需要改配置。删除锁文件、混用包管理器或反复清缓存都可能扩大差异,不能作为第一步。
如果提示找不到构建命令,先确认当前工作目录下是否存在对应的 package.json,其中是否定义了脚本,以及脚本名是否与平台设置一致。框架自动识别可能会套用另一套默认命令,手动配置又可能与框架预设冲突。若脚本已经启动但以非零状态退出,应继续追到脚本内部第一条失败命令;外层的“构建失败”通常只是包装信息。
构建超时或内存不足时,先看超时发生在依赖安装、静态生成、资源处理还是远程内容获取阶段。构建日志的最后一个阶段不一定包含最早原因。若生成器在构建时请求远程数据,网络波动、远程接口限速或内容量过大,都可能让本地与平台表现不同。不要把所有超时都归因于免费构建额度,也不要未经确认就随意提高并发或改变资源限制。
部署提示产物目录不存在、目录为空或生成文件没有进入产物时,应按实际构建结果核对,不能只相信配置页面上的路径。确认输出目录是相对于仓库根目录还是应用目录,检查文件是否写入了嵌套的工作区,查看构建结束时目录是否已经被清空,以及部署上传阶段是否选择了同一目录。命令只能帮助定位,最终仍要把构建结束时的文件树与部署时提交的目录逐项对应。部署成功只说明上传动作完成,不代表入口文件和所有资源都正确。
首页空白,或 CSS、JavaScript、图片请求返回 404 时,先在浏览器网络面板中确认失败资源的完整 URL,再与产物中的实际文件路径比较。常见方向包括输出目录选错、资源仍使用根路径、站点部署在子路径、生成器配置与部署前缀不一致,以及旧 HTML 或旧静态资源被缓存。不要为了让请求暂时成功就随意添加基础路径;先确定站点的最终访问前缀,再同时核对生成配置和资源地址。
子页面直接访问或刷新返回 404,则要把客户端路由和静态文件分发分开看。纯静态 SPA 如果依赖客户端路由,通常需要入口回退或预渲染具体路由;静态服务器不会自动知道每个前端路由应该对应哪个 HTML 文件。哈希路由和真实路径路由的访问行为也不同。回退、重定向和响应头配置具有平台边界,必须按当前官方文档核对,不能把一个平台的设置名称直接复制到另一个平台。
环境变量缺失时,先确认变量是否在构建阶段读取、是否只对生产环境提供,以及是否被错误地当成浏览器变量。静态文件一旦生成,部署后的页面不会自动获得新的服务器变量;修改配置后旧部署仍可能保留旧内容,必须核对新的构建记录和部署时间。排查时记录变量名、作用域和更新时间即可,不要把密钥值贴进日志、工单或文章。
自定义域名异常时,先用平台生成的测试地址验证构建和页面,再检查 DNS 指向、名称服务器、证书签发、代理状态、重定向、响应头和缓存。测试地址正常而自定义域名失败,问题通常不在源码构建;测试地址本身也失败,才回到构建和路由排查。DNS 切换有传播和缓存影响,迁移时不要在自定义域名尚未验证前就撤掉旧站点,至少保留可回退的记录和旧入口。
预览环境正常而生产环境失败时,逐项比较两条部署链路使用的提交版本、仓库根目录、构建命令、输出目录、Node 版本、变量作用域和生产配置。预览与生产可能不是同一套构建输入,不能把预览成功当作生产已验证。更换平台时,仅复制仓库地址不够,环境变量、基础路径、输出目录、DNS、缓存、重定向、响应头和资源版本都需要重新确认;站点前缀变化后,旧缓存中的 HTML 还可能继续引用旧资源。
排障路径明确后,再按站点的实际约束选择平台:
| 主要需求 | 核对重点 |
|---|---|
| 个人技术博客、文档和低频更新的静态内容 | 先比较当前构建额度、访问与存储口径,再看域名维护成本 |
| 带客户端路由的纯静态 SPA | 先确认回退规则、基础路径和资源前缀,再比较两边的构建流程 |
| 需要频繁预览、团队权限和分支协作 | 核对预览保留、并发构建、成员数量、环境变量隔离和商业计划条件 |
| 访问量较大或静态资源很多 | 重点比较请求、流量、缓存、单文件和文件数量限制,不要只看构建次数 |
| 有复杂 DNS、代理、证书或重定向需求 | 选择与现有域名工作流匹配的平台,并先验证官方当前支持范围 |
| 需要 SSR、API、边缘函数或平台适配器 | 单独评估运行时和函数成本,不能继续按纯静态站比较 |
对以文章、文档和静态资源为主的技术博客,通常应先验证本地生产构建、输出文件和自定义域名。至于哪个平台的免费额度更高、哪个平台更适合团队,目前不能脱离具体计划、统计日期和项目形态给出确定答案。
当前仍未解决的问题包括:额度和产品政策可能变化、框架预设是否覆盖项目、运行时函数的真实成本、预览环境的功能边界,以及迁移后 DNS 与缓存的实际表现。本文没有可核验的官方产品证据,也没有把任何平台日志写成作者亲测结果;具体数字、配置字段、错误原文和菜单路径,都应在正式接入时依据最新官方文档重新确认。












暂无评论内容