# @edgeone/is-spa 中文文档

规范地址：https://npmcn.com/package/%40edgeone/is-spa/

版本：0\.0\.4
npm 元数据更新时间：2026-10-26T06:36:57.519Z
中文译文更新时间：2026-11-13T06:42:51.995Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40edgeone/is-spa
原文对照：https://npmcn.com/package/%40edgeone/is-spa/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：60.6 kB，10 个文件
- 模块格式：CommonJS
- TypeScript 类型：未声明
- Node.js 要求：\>=14\.0\.0
- 运行依赖：0 个
- 首次发布：2026-04-13T06:26:35.272Z
- 最新版本发布：2026-10-26T06:36:57.296Z
- 近 30 天下载量：15849（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：4（近 12 个月 4 个）

## 中文简介

检测前端项目是SPA、MPA、Hybrid还是SSG。 确定是否需要 Nginx/ CDN 回落到index.html .

## 安装

```sh
npm install @edgeone/is-spa
```

也可以使用：`pnpm add @edgeone/is-spa`、`yarn add @edgeone/is-spa`、`bun add @edgeone/is-spa`

## README

# is-spa-project

检测前端项目是否为 SPA（单页应用），判断部署时是否需要配置 Nginx/CDN **回源兜底到 `index.html`**。

支持**源码检测**和**构建产物检测**两种模式，覆盖 React、Vue、Angular、Svelte、Next.js、Nuxt、SvelteKit、Remix、React Router 等主流框架。

## 快速开始

```js
const { needsFallback } = require('is-spa-project')

// 传入任意目录，自动判断
needsFallback('./my-project')       // true — 需要配置兜底
needsFallback('./my-project/dist')  // true
needsFallback('./my-nuxt-app')      // false — 不需要兜底
```

## 安装

```bash
npm install is-spa-project
```

## API

### `needsFallback(dir, options?): boolean`

**推荐使用。** 判断是否需要配置回源兜底。

```js
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`

自动识别目录类型，返回完整检测结果。

```js
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

```bash
# 自动模式（自动判断源码/产物）
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 | — | ✅ | ❌ |

路由代码只统计页面实际加载的 JS：HTML 中的 `<script src>` / `<link rel="modulepreload">`，以及这些文件通过静态 `import ... from` / `export ... from` 引用到的 chunk。没有被页面引用的懒加载 chunk 不参与判定，只会出现在 `details.unreferencedRouterJsFiles` 里，便于排查。

关键词按标识符边界匹配，避免 `onpopstate` 这类字符串被语法高亮数据表误命中；`onpopstate` 仅在赋值场景（`window.onpopstate = ...`）才视为路由实现。

产物根目录存在静态 `404.html`（不含 JS 引用）时，认为作者已经声明了 404 语义，不再自动开启回退。如果 `404.html` 本身是带 JS 的应用页面（如 Vue CLI / SvelteKit 生成的辅助页），仍按原逻辑判定。

### `needsFallback` 自动检测

```
传入目录 → 判断是源码还是产物
├── 有 package.json（含 dependencies）或 src/ → 源码检测
└── 否则 → 产物检测
主模式结果 unknown(low) → 回退另一种模式（仅采纳 high 置信度）
构建产物模式：只有 high 置信度、且没有静态 404.html 时才返回 true
```

## 测试

```bash
npm test            # 源码检测（24 个测试项目）
npm run test:dist   # 构建产物检测（24 个测试项目）
npm run test:edge   # 产物检测边界用例
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

## 常见问题

### @edgeone/is-spa 是什么？

检测前端项目是SPA、MPA、Hybrid还是SSG。 确定是否需要 Nginx/ CDN 回落到index\.html \.

### 如何安装 @edgeone/is-spa？

在项目目录运行 npm install @edgeone/is-spa，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 is-spa，可以用 npx is-spa 直接运行。

### @edgeone/is-spa 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/edgeone\_\_is-spa 是否存在。

### @edgeone/is-spa 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @edgeone/is-spa 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=14\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @edgeone/is-spa 可以商用吗？

@edgeone/is-spa 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @edgeone/is-spa 的下载量有多少？

根据 npm 官方下载统计，@edgeone/is-spa 在 2026/10/13 – 2026/11/11 这 30 天内被下载 15,849 次，日均约 528 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @edgeone/is-spa 还在维护吗？

最新版本 0\.0\.4 发布于 2026/10/26（18 天前）；至今共发布 4 个版本，其中过去 12 个月发布了 4 个；首次发布于 2026/04/13。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

