快速开始

本文带你从零创建一个 Swift Web 项目并跑起来,核心流程约 5 分钟(第一步到第五步);后面三步(API / 站点图标 / 自定义图标)按需进行,不做也不影响起步。

第一次接触 Swift Web?不用先读任何架构文档——照着本文逐步执行即可,每一步都写了"做什么、为什么、做完应该看到什么"。

前置条件

开始前确认机器上有这三样:

条件要求怎么检查 / 安装
Node.js^22.22.3 || ^24.15.0 || >=26.0.0node -v;推荐用 nvm 管理版本
pnpm11+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;可多选语言
启用 PWANo注入 Service Worker + manifest
启用 WebSocketNo注册全局 $ws 客户端
启用 Tailwind CSS v4No自动装依赖 + 接入 Vite 插件
是否立即 pnpm installYes同步安装依赖

选择结果写入 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)自动生成,不手写。

后端已就绪

  1. 文档源配置分两处(向后端同学要值)——非秘密写在 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。
  2. 生成:
    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 再做、上线前补上都来得及。

  1. 把 logo 源图放到 app/assets/ 下,二选一:
    • icon.svg(推荐):矢量;还可以在 SVG 里内嵌 @media (prefers-color-scheme: dark) 让 favicon 跟随系统明暗
    • icon.png:业务 logo 只有位图时用(无主题切换能力)

    两个都放时优先用 SVG。
  2. 生成:
    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)时:

  1. 把 SVG 文件放进 app/assets/icons/,文件名即图标名(如 game.svg);
  2. dev 模式下自动生效——starter 内置的 Vite 插件监听这个目录,放入 / 修改 SVG 会立即注入 app/components/AppIcon.vue(写进 <!-- ICONS:START --> 标记区)并热更新,通常什么命令都不用跑;
  3. 模板里直接用:
    <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 编号派生,如 yc001
  • project.type — 锁死为 'web',sw config set project.type 会报 TYPE_LOCKED
  • project.title / description — 用于 nuxt.config.ts 的 title / meta
  • framework.* — 框架能力开关,与 nuxt.config.ts 的 swiftConfig 联动,sw config set 会同步更新 nuxt.config.ts
  • framework.tracker — 打点底座开关(默认开,向导不询问);关闭上报用 sw config set framework.tracker.enabled false
  • features.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-checkNuxt TypeScript 类型检查
pnpm test运行 Vitest 单元测试(一次性)
pnpm test:watchVitest 监听模式
pnpm test:coverageVitest 覆盖率
pnpm test:e2ePlaywright 端到端测试
pnpm test:e2e:ui以 UI 模式运行 Playwright 测试

所有 pnpm <script> 都可以等价写成 sw run <script>(AI 工具 / 终端统一入口)。不确定有哪些脚本时,在项目根目录跑 sw run 列出全部脚本及一句话描述。

下一步

  • 阅读 CLI 命令参考 了解所有 sw 命令(含 sw run,starter 自带 MCP 配置让 AI 工具链开箱即用)
  • 阅读 开发规范 了解团队开发约定
  • 阅读 框架配置 了解 swiftConfig 所有选项