ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

零成本上线插件官网:万网域名 + Cloudflare Pages + Nuxt 4 全流程实录

2026/10/1 20:45:32 拓冰建站 浏览量
零成本上线插件官网:万网域名 + Cloudflare Pages + Nuxt 4 全流程实录 适合谁做 Chrome 扩展、小工具、出海小产品的独立开发者手里有一个域名想给每个产品挂一个子域名官网不想买服务器、不想备案、不想花钱。最终效果主站 品牌页 插件列表子站 单个插件的图文落地页、隐私政策、服务条款、联系页代码放 GitHubgit push后 Cloudflare 自动构建、自动上线全程 HTTPS花费除了域名本身0 元目录整体架构与选型为什么是 Cloudflare 而不是阿里云 OSS准备工作第一步把域名加入 Cloudflare第二步在万网阿里云把 DNS 服务器改到 Cloudflare第三步验证 Cloudflare 账号邮箱很多人卡在这里第四步先用拖拽上传快速上线一个页面第五步用 Nuxt 4 搭建正规的静态官网第六步代码推到 GitHub第七步Cloudflare Pages 连接 GitHub实现推送即部署第八步把自定义域名从旧项目迁移到新项目第九步绑定根域名和 www日常更新流程踩坑汇总重点免费额度与限制附录完整配置文件1. 整体架构与选型1.1 目标插件少的时候主域名撑不起一个应用商店式的列表页但每个插件都需要一个能填进 Chrome 应用商店的Homepage URL一个隐私政策链接商店审核必填一个有图有文、能承接搜索流量的落地页所以方案是一个插件一个子域名一个子域名一个独立项目。goodexts.com → goodexts-website 仓库 → Cloudflare Pages 项目 A www.goodexts.com → 同上同一个项目绑两个域名 xdown.goodexts.com → xdown-website 仓库 → Cloudflare Pages 项目 B xxx.goodexts.com → 以后每加一个插件就再建一个仓库 一个项目好处各插件站互不影响改一个不会把另一个搞挂以后某个插件要单独卖、单独迁移整个仓库拿走即可主站只维护一个插件列表指向各子站1.2 为什么不用阿里云 OSS我一开始也考虑过 OSS 静态托管对比下来放弃了问题阿里云 OSSCloudflare Pages备案大陆区域的 Bucket 绑自定义域名必须 ICP 备案13 周境外托管不需要备案默认域名预览 HTML大陆 Bucket 默认域名会强制下载 HTML自带xxx.pages.dev可直接访问HTTPS要自己申请、上传、续期证书或再套 CDN自动签发、自动续期多子域名每个子域名一个 Bucket 或 CDN 配置一个项目点一下添加自定义域名费用存储 流量 请求计费静态托管免费自动部署要自己写 CI连 GitHub 即可唯一的考量是用户在哪。Chrome 扩展的用户本来就在海外国内访问不了 Chrome 应用商店Cloudflare 在国内偶尔慢的问题对我不构成影响。如果你的用户主要在国内才需要认真考虑备案 国内 CDN。1.3 这套方案里用到了什么组件作用费用万网阿里云域名域名注册商只负责续费域名年费Cloudflare DNS接管域名解析免费Cloudflare Pages静态网站托管 自动构建 HTTPS CDN免费GitHub代码仓库私有仓库也免费免费Nuxt 4静态站点生成SSG开源网上流行的 “Pages Workers D1 R2 Resend 全家桶零成本” 说法做官网只需要 Pages 这一个。Workers、D1、R2 是做登录、支付、存储这些后端能力时才需要的等真用到再加别一开始就上。2. 准备工作一个已购买的域名本文以万网购买的goodexts.com为例一个 Cloudflare 账号dash.cloudflare.com/sign-up免费计划不需要绑信用卡一个 GitHub 账号本地环境Node.js 22、pnpm本文用 pnpm 11、git、GitHub CLIgh可选但很省事node-v# v22.xpnpm-v# 11.xgh auth status3. 第一步把域名加入 Cloudflare登录 Cloudflare 控制台左侧Domains → Overview点Add a domain新版界面是 “Connect a domain”。输入根域名goodexts.com注意不要带 www、不要带 https。DNS 记录导入方式选Import DNS records automatically推荐。新买的域名一般没有任何记录扫出来是空的没关系。选择计划往下找到Free$0点Select plan。页面上 Pro$20/月的按钮更显眼别点错。进入 “Importing DNS records”等它扫完点Continue to activation。会弹出提示 “Add records later — Without DNS records, Cloudflare is unable to activate your site”直接Confirm。记录我们后面让 Pages 自动加。进入Update your nameservers页面这里是关键信息Add each of your assigned Cloudflare nameservers: adam.ns.cloudflare.com linda.ns.cloudflare.com Delete your other nameservers: dns29.hichina.com dns30.hichina.com注意每个 Cloudflare 账号分配到的两个 nameserver 名字不一样adam / linda 只是我的一定以你自己页面上显示的为准。dnsXX.hichina.com就是万网默认的 DNS 服务器。把这两个 Cloudflare nameserver 复制下来去万网改。4. 第二步在万网阿里云修改 DNS 服务器登录阿里云控制台 →域名与网站 → 域名列表找到你的域名点管理。左侧菜单DNS 管理 → DNS 修改。页面会显示当前 DNS 服务器dns29.hichina.com、dns30.hichina.com。点修改 DNS 服务器进入修改为自定义 DNS第一个输入框填adam.ns.cloudflare.com第二个输入框填linda.ns.cloudflare.com注意结尾不要加点填example.com而不是example.com.不要有空格点确定弹出请确认该操作选手机认证 → 获取验证码填短信验证码再点确定。回到 DNS 修改页面当前 DNS 服务器变成两个 Cloudflare 的地址就说明提交成功了。几个注意点DNSSEC如果你在阿里云开启过 DNSSEC要先在DNS 管理 → DNSSEC 设置里关掉否则切到 Cloudflare 后解析会失败。新买的域名默认没开。生效时间阿里云页面写24–48 小时Cloudflare 写1–2 小时最长 24 小时。我实际是几个小时内就生效了。所有权不变改 DNS 只是把解析交给 Cloudflare域名的注册、续费仍在万网续费照常在阿里云交。原有解析记录会失效如果你之前在阿里云云解析里配过记录比如邮箱 MX切换前要在 Cloudflare 的 DNS 里把它们补上。新域名不用管。回到 Cloudflare 的域名 Overview 页面点Check nameservers now页面变成 “Waiting for your registrar to propagate your new nameservers”等着就行生效后 Cloudflare 会发邮件域名状态变为Active。等待期间不耽误干活下面的步骤可以并行做。5. 第三步验证 Cloudflare 账号邮箱很多人卡在这里第一次进Workers Pages → Create时可能会被一个Verify your account弹窗挡住We sent an email to xxxgmail.com. To verify your account, click the link in the email.坑点注册时 Cloudflare 发过一封验证邮件触发 Pages 时可能又发一封。只有最新的那封有效点旧的会提示成功但控制台依然不认。解决办法在弹窗里点Resend email看到 “Another verification email has been sent.” 后去邮箱找刚收到的那一封点链接。在 Gmail 里注意推广动态分类Cloudflare 的邮件经常被分到那里。验证后回到控制台刷新页面弹窗消失才算完成。6. 第四步先用拖拽上传快速上线一个页面在正式搭框架之前我先用一个纯 HTML 页面把整条链路跑通确认域名、DNS、HTTPS 都没问题。这一步也可以直接跳到第 7 步。Workers Pages → Create → Pages会看到两个选项Import an existing Git repository连 Git 自动部署Drag and drop your files拖拽上传← 这次选这个填项目名比如goodexts-xdown页面会提示 “Your project will be deployed to goodexts-xdown.pages.dev”点Create project。上传文件可以选文件夹也可以传一个 zip。zip 里index.html要在根目录不要多套一层文件夹。看到 “2/2 files uploaded / All files were successfully uploaded” 后点Deploy site。部署完成后访问https://goodexts-xdown.pages.dev确认页面正常。绑定子域名进入项目 →Custom domains → Set up a custom domain。输入xdown.goodexts.com点Continue。Cloudflare 会自动提示要添加的记录TypeNameContentTTLCNAMExdowngoodexts-xdown.pages.devAuto点Activate domain。状态从Initializing变为Active即可访问HTTPS 证书是自动签发的不用做任何事。前提域名的 DNS 必须已经托管在 Cloudflare第 3、4 步。这样 Cloudflare 能自动帮你加 CNAME 记录不用手动去 DNS 页面配。验证一下curl-Ihttps://xdown.goodexts.com/# HTTP/2 200 就是成功拖拽上传的局限每次更新都要手动重新上传而且拖拽上传的项目后续不能改成连接 Git。想要推送即部署得新建一个 Git 项目见第 9、10 步。所以如果你一开始就打算长期维护可以直接跳过这一步。7. 第五步用 Nuxt 4 搭建正规的静态官网一个页面的纯 HTML 很快就不够用了要有首页、隐私政策、服务条款、联系我们还要 SEO、结构化数据、共用页头页脚。我选了 Nuxt 4 做静态生成SSG最终产物仍然是纯静态文件完全适合 Pages 免费托管。7.1 目录结构xdown-website/ ├── app/ │ ├── app.vue # 布局页头 页面 页脚 │ ├── assets/css/main.css # 全站样式CSS 变量做主题 │ ├── components/ │ │ ├── SiteHeader.vue │ │ ├── SiteFooter.vue │ │ └── ContactChannels.vue │ ├── config/site.ts # 站点名、商店链接、联系方式唯一数据源 │ └── pages/ │ ├── index.vue # 首页Hero、功能图文、使用步骤、FAQ、CTA │ ├── privacy-policy.vue │ ├── terms-of-service.vue │ └── contact-us.vue ├── public/ │ ├── images/ # 产品图、分享图 │ ├── icon.png │ ├── _redirects # Cloudflare Pages 重定向规则 │ ├── robots.txt │ └── sitemap.xml ├── nuxt.config.ts ├── package.json └── pnpm-workspace.yamlNuxt 4 的新目录约定页面、组件都放在app/下面和 Nuxt 3 不同。7.2 package.json{name:xdown-website,private:true,type:module,scripts:{dev:nuxt dev,build:nuxt build,generate:nuxt generate,preview:nuxt preview,postinstall:nuxt prepare},dependencies:{nuxt:^4.5.2,vue:^3.5.43,vue-router:^4.5.0}}7.3 nuxt.config.tsimport{site}from./app/config/siteexportdefaultdefineNuxtConfig({compatibilityDate:2026-09-01,devtools:{enabled:false},css:[~/assets/css/main.css],app:{head:{htmlAttrs:{lang:en},meta:[{name:viewport,content:widthdevice-width, initial-scale1}],link:[{rel:icon,type:image/png,href:/icon.png},{rel:apple-touch-icon,href:/icon.png},],},},runtimeConfig:{public:{siteUrl:site.url}},// 预渲染从首页开始爬所有内部链接每个页面都生成成静态 HTMLnitro:{prerender:{crawlLinks:true,routes:[/]}},})7.4 站点配置集中管理联系方式、商店链接只写在一处全站引用改一次处处生效// app/config/site.tsexportconstsite{name:X Video Downloader,url:https://xdown.goodexts.com,storeUrl:https://chromewebstore.google.com/detail/...,parent:{name:GoodExts,url:https://goodexts.com},contact:{email:youexample.com,directChat:https://wa.me/你的号码,whatsappGroup:https://chat.whatsapp.com/邀请码,telegramGroup:https://t.me/邀请码,},}7.5 SEO 要点每个页面用useSeoMetauseHead设置标题、描述、canonical 和分享卡片useSeoMeta({title,description,ogTitle:title,ogDescription:description,ogType:website,ogUrl:site.url,ogImage:${site.url}/images/og-image.png,// 1200×630ogImageWidth:1200,ogImageHeight:630,twitterCard:summary_large_image,})useHead({link:[{rel:canonical,href:site.url}]})首页还加了 JSON-LD 结构化数据SoftwareApplicationFAQPage有机会让 FAQ 直接出现在搜索结果里。7.6 Cloudflare Pages 的重定向文件public/_redirects构建后会原样复制到输出目录Pages 会自动识别/privacy /privacy-policy 301 /privacy/ /privacy-policy 301 /terms /terms-of-service 301 /contact /contact-us 301这一步的意义之前在商店后台填过/privacy/这种旧链接改了页面路径后旧链接也不会 404。7.7 安装与构建pnpm 11 的坑pnpminstallpnpm 10 以后默认不执行依赖的安装脚本会报[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: esbuild0.28.2 Run pnpm approve-builds to pick which dependencies should be allowed to run scripts.esbuild 需要跑安装脚本下载平台二进制不放行的话后面构建会失败。在项目根目录建pnpm-workspace.yamlallowBuilds:esbuild:true再装一次然后生成静态站pnpminstallpnpmgenerate成功时会看到[nitro] Prerendered 10 routes in 0.876 seconds [nitro] √ Generated public .output/public产物目录是.output/public这个路径后面配置 Cloudflare 要用。本地预览npx serve .output/public7.8 产品配图落地页的质感主要靠产品图。我写了一份图片需求单文件名、尺寸、每张图画什么、禁止出现的内容交给 AI 图像工具批量生成然后用 Pillow 统一裁剪和压缩成 WebP文件尺寸用途og-image.png1200×630社交平台分享卡片hero.webp1600×1000首屏大图feature-*.webp1200×900每个功能块的配图图片记得写width、height避免布局跳动首屏图加fetchpriorityhigh其余加loadinglazy。8. 第六步代码推到 GitHub用 GitHub CLI 一条命令建仓库cdxdown-websitegitinitgitsymbolic-ref HEAD refs/heads/main# 老版本 git 不支持 git init -b main 时用这个gitadd-Agitcommit-mInitial Nuxt 4 static sitegh repo create你的用户名/xdown-website--private--source.--remoteorigin--push.gitignore至少包含node_modules .nuxt .output dist .env坑SSH 推送没权限gh repo create会成功创建仓库但如果gh配置的协议是 SSH而本机没有配 SSH key推送会失败Please make sure you have the correct access rights and the repository exists.最省事的办法是改用 HTTPS并让gh充当凭据gitremote set-url origin https://github.com/你的用户名/xdown-website.gitgit-ccredential.helper!gh auth git-credentialpush-uorigin main或者一劳永逸gh auth setup-git9. 第七步Cloudflare Pages 连接 GitHub实现推送即部署9.1 授权 GitHub只需一次Workers Pages → Create → Pages → Import an existing Git repository → Get started。在 GitHub 标签下点Connect GitHub跳到 GitHub 授权页。仓库权限建议选Only select repositories只勾需要部署的仓库比如xdown-website、goodexts-website点Install Authorize。回到 Cloudflare能看到仓库列表就成功了。以后新建网站仓库要去 GitHub → Settings → Applications → Cloudflare Workers and Pages → Configure 里把新仓库勾上。9.2 创建项目与构建配置选中仓库点Begin setup按下表填配置项填写Project namexdown-website决定xxx.pages.dev的前缀Production branchmainFramework presetNone不选也行下面手动填Build commandNITRO_PRESETstatic pnpm generateBuild output directory.output/publicRoot directory留空Environment variablesNODE_VERSION22点Save and Deploy可以看到构建过程Initializing build environment → Cloning git repository → Building application → Deploying。9.3 最大的坑Output directory .output/public not found我第一次构建时Build command 填的是pnpm generate日志前面一切正常最后却失败了[success] [nitro] Generated public dist [info] Generated dist/_headers [info] [nitro] Adding Nitro fallback to _redirects to handle all unmatched routes. ... Validating asset output directory Error: Output directory .output/public not found. Failed: build output directory not found原因Nuxt 的服务端引擎 Nitro 会自动识别运行环境。在 Cloudflare Pages 的构建机里它自动切换成了cloudflare_pages预设产物输出到了dist/而且还往_redirects里塞了一条兜底规则和本地的.output/public完全不同。本地可以复现NITRO_PRESETcloudflare_pagespnpmgeneratels# 出现的是 dist/没有 .output/public解决在构建命令里显式指定静态预设NITRO_PRESETstaticpnpmgenerate这样本地和线上行为一致输出目录固定为.output/public也不会被注入额外的重定向规则。修改后在项目Settings → Build → Build configuration → Edit里保存然后推一个空提交触发重建gitcommit --allow-empty-mTrigger Cloudflare Pages buildgitpush另一种做法是把 Output directory 改成dist用 Cloudflare 的预设。但我只需要纯静态站用static更可控也和本地一致。9.4 验证构建成功后先看预览域名curl-Ihttps://xdown-website.pages.dev/curl-Ihttps://xdown-website.pages.dev/privacy-policycurl-Ihttps://xdown-website.pages.dev/not-exist# 应该返回 40410. 第八步把自定义域名从旧项目迁移到新项目同一个域名同一时间只能绑在一个 Pages 项目上。第 6 步用拖拽上传建的旧项目占着xdown.goodexts.com要先摘下来打开旧项目 →Custom domains在域名那一行点⋯Domain actions→ Remove domain → Remove domain。打开新的 Git 项目 →Custom domains → Set up a custom domain输入xdown.goodexts.com。这次提示的 CNAME 会指向新项目TypeNameContentCNAMExdownxdown-website.pages.devActivate domain。切换期间会有一两分钟访问不到建议先在pages.dev预览地址确认新站没问题再切。旧项目不急着删确认新站稳定后再删也不迟。11. 第九步绑定根域名和 www主站仓库goodexts-website按第 9 步同样的配置建项目然后在同一个项目里添加两个自定义域名域名Cloudflare 自动添加的记录goodexts.comCNAME→goodexts-website.pages.devwww.goodexts.comCNAMEwww→goodexts-website.pages.dev说明根域名能用 CNAME 吗标准 DNS 里根域名不能用 CNAME但 Cloudflare 支持CNAME FlatteningCNAME 展平会自动把它解析成 IP 返回所以这里没问题。这也是域名必须托管到 Cloudflare的原因之一用别家 DNS 时根域名很难这样绑。刚添加时状态是Initializing此时访问可能返回522这是证书和路由还没就绪等几分钟就会变成Active。检查fordingoodexts.com www.goodexts.com xdown.goodexts.com;docurl-s-o/dev/null-w$d%{http_code}\nhttps://$d/done12. 日常更新流程从这以后改网站就是改代码# 改内容本地看一眼pnpmdev# 提交推送gitadd-Agitcommit-mUpdate contact pagegitpush推送后 Cloudflare 自动构建一般 1 分钟左右上线。每次构建在项目的Deployments里都有记录出问题可以一键回滚到任意历史版本。新增一个插件站的完整步骤复制一个现有站点仓库改app/config/site.ts和页面内容gh repo create推到 GitHubGitHub 里给 Cloudflare 应用勾选这个新仓库Cloudflare 新建 Pages 项目构建配置同上添加自定义域名新名字.goodexts.com在主站的插件列表里加一条全程 10 分钟左右。13. 踩坑汇总#现象原因解决1选计划时差点选了 ProPro 按钮是实心蓝色更显眼认准Free $02点了邮件验证链接控制台还弹 “Verify your account”点的是旧邮件弹窗里Resend email点最新那封3阿里云改 DNS 要验证码安全验证提前准备好绑定的手机4切换 DNS 后解析异常开着 DNSSEC先在阿里云关闭 DNSSEC5ERR_PNPM_IGNORED_BUILDSpnpm 默认不跑依赖的安装脚本pnpm-workspace.yaml里allowBuilds: { esbuild: true }6git init -b main报 unknown switch老版本 gitgit symbolic-ref HEAD refs/heads/main7gh repo create --push推送失败用了 SSH 协议但没配 key改 HTTPS gh auth git-credential或gh auth setup-git8Cloudflare 构建报.output/public not foundNitro 在 Cloudflare 自动切到cloudflare_pages预设输出到dist构建命令用NITRO_PRESETstatic pnpm generate9拖拽上传的项目想改成连 Git不支持转换新建 Git 项目把域名迁过去10添加域名提示已被占用同一域名只能绑一个项目先在旧项目 Remove domain11新绑的域名返回 522还在 Initializing等几分钟变 Active12页面源码里的邮箱变成[email protected]Cloudflare 默认开启邮箱地址混淆Scrape Shield正常用户看得到想关闭去域名的Scrape Shield → Email Address Obfuscation13改了 CSS 本地没变化浏览器缓存URL 加?v2或强制刷新14. 免费额度与限制以下以 Cloudflare 官方文档为准政策可能调整上线前建议再核对一遍Pages 静态托管静态资源的带宽和请求不限量对官网类站点基本等于无限。构建次数免费计划每月有构建次数上限约 500 次。一个人维护几个站正常提交远远用不完。单次构建时长、单个项目的文件数和单文件大小都有上限纯静态官网碰不到。Workers / D1 / R2各有自己的免费额度本文方案没用到。等需要后端登录、支付、表单提交、授权校验时再加而且可以只加在某一个子站上。国内访问Cloudflare 在中国大陆偶尔慢或不稳定。面向海外用户的产品不受影响面向国内用户要慎重。15. 附录完整配置文件pnpm-workspace.yamlallowBuilds:esbuild:truepublic/_redirects/privacy /privacy-policy 301 /privacy/ /privacy-policy 301 /terms /terms-of-service 301 /contact /contact-us 301public/robots.txtUser-agent: * Allow: / Sitemap: https://xdown.goodexts.com/sitemap.xmlpublic/sitemap.xml?xml version1.0 encodingUTF-8?urlsetxmlnshttp://www.sitemaps.org/schemas/sitemap/0.9urllochttps://xdown.goodexts.com//loc/urlurllochttps://xdown.goodexts.com/contact-us/loc/urlurllochttps://xdown.goodexts.com/privacy-policy/loc/urlurllochttps://xdown.goodexts.com/terms-of-service/loc/url/urlsetCloudflare Pages 构建配置Build command: NITRO_PRESETstatic pnpm generate Build output directory: .output/public Root directory: (留空) Production branch: main Environment variables: NODE_VERSION 22最终 DNS 记录Cloudflare 自动生成TypeNameContentProxyCNAMEgoodexts-website.pages.dev已代理CNAMEwwwgoodexts-website.pages.dev已代理CNAMExdownxdown-website.pages.dev已代理写在最后整套流程走下来真正需要等待的只有 DNS 生效这一步其余都是点几下的事。真正花时间的是官网内容本身产品图、功能文案、FAQ、隐私政策。基础设施零成本、零运维之后精力就可以全部放回产品上。线上效果主站https://goodexts.com插件子站https://xdown.goodexts.com