npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@edgeone/is-spa

v0.0.3

Published

Detect whether a frontend project is SPA, MPA, Hybrid, or SSG. Determine if Nginx/CDN fallback to index.html is needed.

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-project

API

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