快速开始
本文带你从零创建一个 Swift Web 项目并跑起来,核心流程约 5 分钟(第一步到第五步);后面三步(API / 站点图标 / 自定义图标)按需进行,不做也不影响起步。
第一次接触 Swift Web?不用先读任何架构文档——照着本文逐步执行即可,每一步都写了"做什么、为什么、做完应该看到什么"。
前置条件
开始前确认机器上有这三样:
| 条件 | 要求 | 怎么检查 / 安装 |
|---|---|---|
| Node.js | ^22.22.3 || ^24.15.0 || >=26.0.0 | node -v;推荐用 nvm 管理版本 |
| pnpm | 11+ | pnpm -v;没有就 npm install -g pnpm |
| 私仓权限 | 能访问内部 npm 私服 | 第一步的安装脚本会自动配置,无需手动 |
开发与构建推荐 Node.js 26.13.0 LTS、pnpm 12.16.1。开发机、CI 作业与服务器的 Node 版本可以不同;服务器按实际依赖的
engines校验,使用 Nuxt 4.6.4 时 Node 24 至少为 24.15.0,无需跟随开发机升级到 26。
为什么 pnpm 必须 11+:starter 的
engines.pnpm: ">=11"是硬闸——低版本跑pnpm install会直接报ERR_PNPM_UNSUPPORTED_ENGINE并中止,这是刻意设计(pnpm 11 起默认开启供应链安全策略)。
第一步:安装 CLI
sw 是 Swift Web 的脚手架命令,装一次全局可用。
macOS / Linux
curl -sSL https://sw.djatm.cloud/install.sh | bash
脚本一键完成:检查 Node.js → 安装并验证 pnpm(如缺少)→ 初始化全局命令目录与当前脚本的 PATH → 配置私仓地址 → 全局安装 @swift-web/cli。
若提示 Corepack 缓存中的 pnpm.cjs 缺失,先用 pnpm 官方安装脚本重新安装 pnpm,成功后重新打开终端再试。安装脚本会保留原始错误,并在 pnpm 或 pnpm setup 失败时中止。安装成功后,已打开的终端若找不到 sw,重新打开终端加载新的 PATH。
Windows(PowerShell)
irm https://sw.djatm.cloud/install.ps1 | iex
Windows 需要先自行安装 Node.js(^22.22.3 || ^24.15.0 || >=26.0.0);PowerShell 5.1+(Windows 10/11 默认内置)。
手动安装
如果不想用一键脚本,分两步手动来。先配置私有 npm 仓库(每台机器只需一次):
macOS / Linux:
echo '@swift-web:registry=https://npm.djatm.cloud/' >> ~/.npmrc
Windows(PowerShell):
Add-Content "$env:USERPROFILE\.npmrc" "`n@swift-web:registry=https://npm.djatm.cloud/"
再全局安装:
pnpm add -g @swift-web/cli
发布当天升级装到旧版? pnpm ≥11 默认有 24 小时「冷静期」(
minimumReleaseAge),刚发布的版本一天内解析不到,pnpm add -g会静默装到上一版。项目里pnpm-workspace.yaml的豁免管不到全局安装,要在用户级~/.npmrc加一行minimumReleaseAgeExclude[]=@swift-web/*(一键安装脚本已自动写入),或临时钉版本pnpm add -g @swift-web/cli@<版本>。
验证安装
sw -v
# 输出类似:0.8.x(以当前安装的 @swift-web/cli 版本为准)
能打印出版本号就说明装好了。
第二步:创建项目
用 sw create 初始化新项目。出于仓库命名一致性,它只接受两种格式:
YC 格式(内部项目的强制命名)
sw create YC001-WEB-项目名称
命名规则:YC + 数字编号 + -WEB- + 中文或英文项目标题,大小写不敏感。
示例:
sw create YC117-WEB-影城管理系统
# 生成目录:yc117_web/
# 项目 name:yc117
# 项目 title:影城管理系统
CLI 自动从名字里提取 name 和 title,不再重复询问。
在当前目录初始化(.)
已经手工建好目录、或想直接在仓库根目录创建时,传 .:
mkdir my-project && cd my-project
sw create .
此时 CLI 会交互式询问项目标题和描述;project.name 取当前目录名。
普通字符串项目名会被拒绝(如
sw create my-project)——保证所有内部项目都能从仓库名一眼识别出编号。
交互式配置向导
创建过程中 CLI 会依次询问是否启用以下能力(不确定就直接回车选默认,以后都能用 sw config set 改,不是一锤子买卖):
| 问题 | 默认 | 作用 |
|---|---|---|
| 主题模式 | 固定浅色 | light / dark / system(跟随系统)/ toggle(用户可切,挂 useTheme() + SwThemeSwitch;再追问三态 / 两态) |
| 启用多语言(i18n) | No | 集成 @nuxtjs/i18n;可多选语言 |
| 启用 PWA | No | 注入 Service Worker + manifest |
| 启用 WebSocket | No | 注册全局 $ws 客户端 |
| 启用 Tailwind CSS v4 | No | 自动装依赖 + 接入 Vite 插件 |
| 是否立即 pnpm install | Yes | 同步安装依赖 |
选择结果写入 swift.config.json,并同步修改 nuxt.config.ts / i18n/locales/ 等相关文件。
非交互模式(CI / 脚本)
sw create YC001-WEB-项目名称 --yes # 跳过交互,全部用默认值
sw create YC001-WEB-项目名称 --yes --json # 额外输出结构化 JSON,便于脚本解析
第三步:进入项目目录
cd yc001_web # 目录名根据 YC 编号自动生成
交互模式下 CLI 已经问过"是否立即安装依赖?"——选了 Yes 就不用再手动 pnpm install。
第四步:配置环境变量
sw create 已自动把 .env.dev.example 复制为 .env,直接编辑即可(不需要自己 cp):
# 编辑 .env,至少填写两个必填项:
NUXT_PUBLIC_SITE_URL=http://localhost:3000
NUXT_PUBLIC_API_BASE=https://api.your-domain.com
NUXT_PUBLIC_SITE_URL:站点自己的地址,本地开发先填http://localhost:3000就行。 ⚠️ 它还有第二重作用:配了它,canonical / og:url / sitemap 会收敛到该域名、不再跟随用户实际访问的域名。单域名站没影响;多域名(防封域名)站应留空,让各镜像自引用、独立被收录(详见 SEO 指南)NUXT_PUBLIC_API_BASE:后端 API 地址——还没有后端?没关系,先随便留着,第六步会讲怎么在没后端的情况下开发
其余字段(YAPI 代码生成等开发期工具配置)按需填写,示例文件里每一行都有注释说明。cookie 名 / 缓存前缀 / AES 密钥等项目常量不在 .env ——它们随代码写在 nuxt.config.ts 的 runtimeConfig 默认值里,构建产物自包含、部署后运行时零必填 env(临时覆盖可用同名 NUXT_PUBLIC_* 进程环境变量)。
.env在.gitignore里不会提交,敏感密钥通过安全渠道在团队内共享。
第五步:启动开发服务器
pnpm dev
看到以下输出即启动成功:
➜ Local: http://localhost:3000/
➜ Network: http://0.0.0.0:3000/
浏览器打开 http://localhost:3000,看到 Starter 首页就算跑通了。🎉
到这里项目已经能跑了。 下面三步是起步后的常见事项——都不阻塞开发,按你的实际节奏做:
| 步骤 | 什么时候做 | 不做会怎样 |
|---|---|---|
| 第六步 · 初始化 API | 后端 + YAPI 文档就绪后 | 没法调真实接口;可用 systemInfo: false 先做静态页 |
| 第七步 · 生成站点图标 | 拿到产品 logo 后,上线前做完即可 | 浏览器标签页是默认图标,不影响功能 |
| 第八步 · 自定义 SVG 图标 | 页面需要业务图标时随用随加 | 无影响 |
第六步:初始化 API(后端就绪后)
项目的 API 类型和请求函数由脚本从接口文档(YAPI 或 OpenAPI 3 spec)自动生成,不手写。
后端已就绪
- 文档源配置分两处(向后端同学要值)——非秘密写在
nuxt.config.ts的swiftConfig.apiDocs(入库随仓走,模板里有占位块),秘密只留.env:// nuxt.config.ts → swiftConfig apiDocs: { source: 'yapi', url: 'https://your-yapi-host.com', project: 123 },# .env —— 只放 token API_DOCS_TOKEN=xxxxxxxx
OpenAPI 源同理:source填openapi、url填 spec 地址,spec 不在鉴权后面就不需要 token。 - 生成:
sw run generate-api
完成后app/api/index.ts、app/api/modules/*.ts、app/api/types/*.ts就是当前后端接口的完整快照,页面里直接api.模块.方法()调用。后端接口有变化时重跑一次即可。
后端 / YAPI 还没就绪:先做静态页
项目初期后端框架还没搭好、YAPI 文档还没生成是常态。此时想先开发不调接口的静态页面,把 nuxt.config.ts 里 swiftConfig 的 systemInfo 临时设为 false:
// nuxt.config.ts → swiftConfig
systemInfo: false, // 临时:跳过启动时拉取 /system/info(后端没好时整站不拉)
这是什么:framework 启动时默认会请求后端的 /system/info 拿站点配置(站点标题、图片解密密钥、菜单、埋点配置等)。后端不存在时这个请求会失败刷错——关掉它,静态页面开发就清净了。
- 关闭期间依赖
/system/info的能力(.bnc加密图解密、后端菜单、埋点配置等)拿不到数据,纯静态开发无影响;- 若登录后端也未就绪,dev 控制台可能还有登录接口的报错,不影响静态页面——介意的话可在
swiftConfig.auth一并关闭(见框架配置);- 后端就绪后记得改回(删掉
systemInfo: false这行恢复默认),再回到上面跑sw run generate-api。
第七步:生成站点图标(拿到 logo 后)
这一步生成浏览器标签页 favicon 和 PWA 应用图标。不必在项目创建后立刻做——拿到产品 logo 再做、上线前补上都来得及。
- 把 logo 源图放到
app/assets/下,二选一:icon.svg(推荐):矢量;还可以在 SVG 里内嵌@media (prefers-color-scheme: dark)让 favicon 跟随系统明暗icon.png:业务 logo 只有位图时用(无主题切换能力)
两个都放时优先用 SVG。 - 生成:
sw run generate-icons
一条命令输出全套:产物 用途 public/favicon.svg现代浏览器标签页图标(仅 SVG 输入时生成) public/favicon.png(48×48)标签页 PNG 兜底 public/icons/apple-touch-icon.png(180×180)iOS Safari「添加到主屏」 public/icons/icon-192.png/icon-512.pngPWA manifest 图标
没开 PWA 也可以放心跑——PWA 尺寸的图标生成了也只是静静躺在
public/icons/,不产生任何副作用;将来开启 PWA 时@vite-pwa/nuxt会自动接管 manifest 并引用它们。
第八步:自定义 SVG 图标(随用随加)
页面里需要业务图标(导航、按钮、状态标识等 SVG)时:
- 把 SVG 文件放进
app/assets/icons/,文件名即图标名(如game.svg); - dev 模式下自动生效——starter 内置的 Vite 插件监听这个目录,放入 / 修改 SVG 会立即注入
app/components/AppIcon.vue(写进<!-- ICONS:START -->标记区)并热更新,通常什么命令都不用跑; - 模板里直接用:
<AppIcon name="game" /> <AppIcon name="game" :width="32" color="var(--primary)" />
极少数情况(比如没开 dev server 时批量加图标)才需要手动执行
sw run inject-icons触发一次注入。注意区分:业务 SVG 图标走
AppIcon(本节);通用 UI 图标(箭头/关闭等)用图标库如@phosphor-icons/vue;位图内容图用SwImage。选型详见开发规范 · 图像资产选型。
给 AI 用的:MCP 能力(零配置自带)
如果你用 Claude Code / Cursor 等 AI 编程工具开发,这一节会让效率翻倍——而且什么都不用配:starter 自带 MCP 配置(内容就是启动 sw --mcp)——Claude Code 读 .mcp.json,Cursor 读 .cursor/mcp.json,两份都已入库、内容相同,AI 工具打开项目目录即自动接入 Swift Web 的 MCP server。
有哪些能力
| 分组 | MCP 工具 | 作用 |
|---|---|---|
| 脚手架 | sw_add_page / sw_add_component / sw_add_store / sw_add_api | 按规范模板新建页面 / 组件 / store / API 模块 |
| 项目配置 | sw_config_get / sw_config_set / sw_config_sync | 读写 swift.config.json 并联动 nuxt.config.ts |
| 脚本执行 | sw_run | 列出 / 执行 package.json 里的任意脚本(generate-api / generate-icons / test…) |
| 文档查询 | sw_framework_docs | 查当前安装版本的 framework 组件 / composable / store / util / 配置文档(富 JSDoc + 示例 + props + 关联 gotcha),不传名则列目录 |
| 接口查询 | sw_project_apis | 查当前项目后端 API 清单(解析 app/api 生成物),开发页面业务前先查该调哪个接口 |
| 项目信息 | sw_info / sw_version / sw_upgrade / sw_create | 项目元信息 / CLI 版本 / 检查升级 / 创建项目 |
自然语言驱动示例
接入后你不需要记任何命令,对 AI 说人话即可:
你:帮我新建一个"关于我们"页面 AI:调用
sw_add_page创建app/pages/about-us.vue(已含defineRouteRules/useSeo模板),然后接着填充内容。
你:这个项目开了哪些框架能力? AI:调用
sw_config_get读取swift.config.json,告诉你 theme / i18n / pwa / tracker 的当前开关状态。
你:SwImage 都有什么 props?加密图怎么用? AI:调用
sw_framework_docs("SwImage")拿到你装的这个版本的完整文档作答——比翻文档站更准(不会有版本错位)。
你:后端 YAPI 更新了,同步一下接口 AI:调用
sw_run("generate-api")重新生成app/api/,并汇报变更。
你:把多语言打开 AI:调用
sw_config_set("framework.i18n.enabled", true)——自动解开 nuxt.config 注释、创建语言文件骨架。
你:帮我建一个用户收藏的 store AI:调用
sw_add_store生成app/store/user-favorites.ts(Pinia 规范模板),再按需求填充 state / action。
你:framework 出新版了吗?帮我升级 AI:调用
sw_upgrade检查私服最新版本并执行升级(内部改写 package.json 的 framework 版本范围,再跑pnpm install --lockfile-only与pnpm install --frozen-lockfile),升级完提醒你重启 dev server。
你:加一个"排行榜"页面,内容一小时更新一次就行 AI:调用
sw_add_page创建app/pages/ranking.vue,并把模板里的defineRouteRules改成{ isr: 3600 }——工具管骨架,渲染策略这类判断由 AI 结合上下文补上。
为什么这很重要:AI 通过 MCP 拿到的是结构化、带版本的事实(而不是凭训练记忆猜 API),加上项目里的
CLAUDE.md协作规范,AI 产出的代码天然符合本框架约定。这正是 Swift Web「AI 友好」设计初衷的落地。
这里只演示常见几类;完整 15 个 MCP 工具与全部可配字段见 CLI 命令参考 · AI 工具链(MCP)。
生成的项目结构
sw create 从 verdaccio 私服(npm.djatm.cloud)npm pack @swift-web/starter 拉最新 starter 模板,解压后替换占位符。当前骨架如下(具体内容随 starter 迭代而变化):
yc001_web/
├── app/
│ ├── components/ 业务组件(AppHeader / AppFooter / LoginForm / TabBar 等)
│ ├── pages/ 路由页面(index / login / register / mine / ...)
│ ├── layouts/ 布局(default.vue / empty.vue)
│ ├── composables/ 业务级 composable
│ ├── store/ 业务级 Pinia store
│ ├── api/ API 请求模块(第六步 generate-api 生成)
│ ├── assets/ CSS 变量与全局样式、图标源图(icon.svg)、icons/ 业务 SVG
│ ├── middleware/ 业务级路由守卫
│ ├── plugins/ 业务级插件
│ ├── utils/ 业务工具函数
│ ├── constants/ 业务常量
│ ├── types/ 业务类型定义
│ └── app.vue / error.vue 应用入口 / 全局错误页
├── public/ 静态资源(images / icons / favicon——第七步 generate-icons 产物)
├── i18n/ 多语言翻译文件(仅启用 i18n 时生成,按所选语言裁剪)
├── server/ Nitro 服务端 API
├── scripts/ 构建脚本(inject-icons / optimize-images / generate-api 等薄封装)
├── tests/ 测试(unit / nuxt 单测 + e2e Playwright)
├── config/ 运行时配置(env 校验等)
├── types/ 全局类型声明
├── patches/ pnpm patch 补丁
├── deploy/ 生产部署脚本 deploy-prod.sh(`pnpm deploy:prod` 入口)
├── .env.dev.example 环境变量示例(提交到 git;生产对应 .env.prod.example)
├── .env 本地环境变量(sw create 自动生成,不提交 git)
├── .mcp.json MCP 配置(Claude Code;Cursor 读 .cursor/mcp.json,内容相同)
├── .gitlab-ci.yml CI 检查(类型 / lint / 单测覆盖率 / 构建)
├── CLAUDE.md AI 协作规范(另有 .cursor/ .github/ 等 AI 工具约定文件)
├── nuxt.config.ts Nuxt 配置(含 swiftConfig 选项——第六步的 systemInfo 就在这里)
├── swift.config.json Swift Web 项目元数据
├── tsconfig.json TypeScript 配置(另有 eslint / stylelint / prettier / playwright / vitest 各自 config)
└── ecosystem.config.cjs PM2 生产进程配置(另有 ecosystem.dev.config.cjs 测试环境用;共机测试须改唯一 PORT)
swift.config.json
Swift Web 的项目配置文件,sw 命令靠它识别 Swift Web 项目。--yes 模式创建后的默认结构:
{
"project": {
"name": "yc001",
"type": "web",
"title": "项目名称",
"description": ""
},
"framework": {
"theme": { "mode": "light" },
"i18n": { "enabled": false, "defaultLocale": "zh-CN", "locales": ["zh-CN"] },
"pwa": false,
"websocket": false,
"errorHandler": false,
"tracker": { "enabled": true, "autoPageView": true }
},
"features": {
"tailwind": false
}
}
字段说明:
project.name— 项目 npm 包名前缀(小写),由 YC 编号派生,如yc001project.type— 锁死为'web',sw config set project.type会报TYPE_LOCKEDproject.title/description— 用于nuxt.config.ts的 title / metaframework.*— 框架能力开关,与nuxt.config.ts的swiftConfig联动,sw config set会同步更新nuxt.config.tsframework.tracker— 打点底座开关(默认开,向导不询问);关闭上报用sw config set framework.tracker.enabled falsefeatures.tailwind— Tailwind v4 开关;sw config set features.tailwind true自动装依赖、改配置、建tailwind.css
常用开发命令
| 命令 | 说明 |
|---|---|
pnpm dev | 启动开发服务器(热更新) |
pnpm build | 构建生产版本 |
pnpm analyze | 构建并打开 bundle 体积分析 |
pnpm preview | 本地预览生产构建 |
pnpm generate | 静态站点生成(SSG) |
pnpm clean | 清除 .nuxt 缓存目录 |
pnpm generate-api | 从 YAPI 自动生成 API 类型和请求函数(第六步) |
pnpm generate-icons | 从 app/assets/icon.svg 生成 favicon + PWA 图标(第七步) |
pnpm optimize-images | 批量压缩 public/images/ 下的图片并生成多种格式 |
pnpm inject-icons | 手动把 assets/icons/ 的 SVG 注入 AppIcon(dev 期自动,一般不用) |
pnpm lint | 串行运行 eslint + stylelint(含 --fix) |
pnpm type-check | Nuxt TypeScript 类型检查 |
pnpm test | 运行 Vitest 单元测试(一次性) |
pnpm test:watch | Vitest 监听模式 |
pnpm test:coverage | Vitest 覆盖率 |
pnpm test:e2e | Playwright 端到端测试 |
pnpm test:e2e:ui | 以 UI 模式运行 Playwright 测试 |
所有
pnpm <script>都可以等价写成sw run <script>(AI 工具 / 终端统一入口)。不确定有哪些脚本时,在项目根目录跑sw run列出全部脚本及一句话描述。