Package Exports
- @edgeone/is-spa
Readme
is-spa-project
检测前端项目是否为 SPA(单页应用),判断部署时是否需要配置 Nginx/CDN **回源兜底到 index.html**。
支持源码检测和构建产物检测两种模式,覆盖 React、Vue、Angular、Svelte、Next.js、Nuxt、SvelteKit、Remix、React Router 等主流框架。
快速开始
const { needsFallback } = require('is-spa-project')
// 传入任意目录,自动判断
needsFallback('./my-project') // true — 需要配置兜底
needsFallback('./my-project/dist') // true
needsFallback('./my-nuxt-app') // false — 不需要兜底安装
npm install is-spa-projectAPI
needsFallback(dir, options?): boolean
推荐使用。 判断是否需要配置回源兜底。
const { needsFallback } = require('is-spa-project')
// 自动模式(默认)— 自动判断源码/产物
needsFallback('./cra-spa') // true
needsFallback('./cra-spa/build') // true
needsFallback('./nuxt-app') // false
// 强制源码检测
needsFallback('./my-project', { mode: 'source' })
// 强制构建产物检测
needsFallback('./my-project/dist', { mode: 'dist' })options.mode:
| 值 | 说明 |
|---|---|
'auto'(默认) |
自动判断目录是源码还是构建产物 |
'source' |
强制源码检测(分析 package.json、配置文件) |
'dist' |
强制构建产物检测(分析 HTML 和 JS 文件) |
autoDetect(dir): DetectionResult
自动识别目录类型,返回完整检测结果。
const { autoDetect } = require('is-spa-project')
const result = autoDetect('./my-project')
console.log(result.mode) // 'source' | 'dist'
console.log(result.type) // 'spa' | 'mpa' | 'hybrid' | 'ssg' | 'unknown'
console.log(result.confidence) // 'high' | 'medium' | 'low'
console.log(result.reason) // 人类可读的判定原因detect(projectRoot): DetectionResult
源码检测模式。分析 package.json、配置文件、入口文件。
detectBuildOutput(distDir): DetectionResult
构建产物检测模式。分析 HTML 文件和 JS bundle 中的路由代码。
isSpa(projectRoot): boolean
源码检测简化版,等价于 detect().type === 'spa' || 'hybrid'。
CLI
# 自动模式(自动判断源码/产物)
npx is-spa ./my-project
npx is-spa ./my-project/dist
# 强制构建产物模式
npx is-spa ./my-project/dist --dist
# JSON 输出
npx is-spa ./my-project --json
npx is-spa ./my-project/dist --dist --json检测结果类型
| 类型 | 含义 | 需要兜底? | 部署配置 |
|---|---|---|---|
| spa | 构建产物只有单个 index.html |
✅ 需要 | try_files $uri $uri/ /index.html |
| hybrid | SPA 主体 + 独立辅助页面 | ✅ 需要 | 主入口需要兜底 |
| mpa | 多个独立 HTML 入口 | ❌ 不需要 | 每个路由有对应文件 |
| ssg | SSR/SSG 框架,每个路由有对应 HTML | ❌ 不需要 | 框架构建工具自动处理 |
| unknown | 无法判定 | ❌ 不需要 | — |
支持的框架和路由库
框架检测(快速路径)
| 框架 | 依赖 | 默认判定 | 可切换为 SPA? |
|---|---|---|---|
| Create React App | react-scripts |
spa | — |
| Angular CLI | @angular/cli |
spa | — |
| Next.js | next |
ssg | ❌ |
| Nuxt | nuxt |
ssg | ❌(generate 自动处理) |
| Gatsby | gatsby |
ssg | ❌ |
| React Router (Framework) | @react-router/dev |
ssg | ✅ ssr: false → spa |
| SvelteKit | @sveltejs/kit |
ssg | ✅ fallback → spa |
| Remix | @remix-run/react |
ssg | ✅ ssr: false → spa |
路由库检测
| 路由库 | 生态 |
|---|---|
vue-router |
Vue |
react-router-dom / react-router |
React |
@tanstack/react-router |
React |
wouter |
React |
@angular/router |
Angular |
svelte-routing |
Svelte |
svelte-spa-router |
Svelte |
page (page.js) |
Vanilla JS |
navigo |
Vanilla JS |
universal-router |
Vanilla JS |
检测原理
源码检测
package.json → 匹配已知框架?→ 框架快速路径(可能读取配置文件)
↓ 否
检测路由库依赖 + 入口文件数量 + router 使用 → 综合判定构建产物检测
根目录有 index.html?
├── 没有 → unknown(不存在回源目标)
└── 有 → 扫描 HTML + JS → 判定| 信号 | SPA | SSG | MPA |
|---|---|---|---|
| 应用 HTML 数 | 1 | 多个 | 多个 |
| HTML body | 空壳 | 有预渲染内容 | 有各自内容 |
| JS 含路由代码 | ✅ | ✅ | ❌ |
| 多 HTML 共享 JS | — | ✅ | ❌ |
needsFallback 自动检测
传入目录 → 判断是源码还是产物
├── 有 package.json(含 dependencies)或 src/ → 源码检测
└── 否则 → 产物检测
主模式结果 unknown(low) → 回退另一种模式(仅采纳 high 置信度)测试
npm test # 源码检测(24 个测试项目)
npm run test:dist # 构建产物检测(24 个测试项目)
npm run test:all # 全部运行测试覆盖 24 个项目:CRA、Vite+React、Vite+Vue、Angular、Vue CLI(SPA/MPA/Hybrid)、Next.js、Nuxt(SSG/SPA)、SvelteKit(SSG/SPA)、Remix(SSR/SPA)、React Router Framework(SPA)、TanStack Router、wouter、svelte-routing、svelte-spa-router、page.js、navigo、universal-router、原生 HTML(单页/多页)。
License
MIT