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

@uni-helper/vite-plugin-uni-manifest

v0.4.1

Published

File system based routing for uni-app applications using Vite

Readme

@uni-helper/vite-plugin-uni-manifest

使用 TypeScript 编写 uni-appmanifest.json

不想看文档?直接问 AI 🤖

安装

pnpm i -D @uni-helper/vite-plugin-uni-manifest

使用

// vite.config.ts
import Uni from '@dcloudio/vite-plugin-uni'
import UniManifest from '@uni-helper/vite-plugin-uni-manifest'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [UniManifest(), Uni()]
})

创建 manifest.config.(ts|mts|cts|js|cjs|mjs|json),然后用 TypeScript 编写你的 manifest.json

// manifest.config.ts
import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'

export default defineManifestConfig({
  // 属性参考 manifest.json,理论上一比一对齐
  // 如果发现没有对齐,请提交 issue,谢谢 🙏
  // https://uniapp.dcloud.net.cn/collocation/manifest.html
  name: "my-project",
})

这里,你可以找到 uni-app 默认的 Vite-TS 模版的 manifest.json 是如何用 TypeScript 编写的。

插件配置

UniManifest() 支持以下选项定义行为:

interface Options {
  /**
   * 是否压缩生成的 manifest.json(去除缩进和换行)。
   * @default false
   */
  minify?: boolean

  /**
   * 是否在 manifest.json 末尾插入换行。
   * @default false
   */
  insertFinalNewline?: boolean

  /**
   * 解析配置的工作目录。
   * 插件会从该目录查找 `manifest.config.(ts|mts|cts|js|cjs|mjs|json)` 文件。
   * @default process.env.VITE_ROOT_DIR
   */
  cwd?: string
}

minify

默认生成的 manifest.json 是格式化后的(缩进 2 空格)。开启 minify 后会输出紧凑的 JSON,减少文件体积。

UniManifest({ minify: true })

insertFinalNewline

控制在生成的 manifest.json 末尾是否追加一个换行符。开启后符合 POSIX 文件规范,部分工具链可能会要求文件以换行结尾。

UniManifest({ insertFinalNewline: true })

cwd

指定插件查找 manifest.config.* 配置文件的目录。如果未设置,会使用 process.env.VITE_ROOT_DIR(由 @dcloudio/vite-plugin-uni 注入的环境变量),通常无需手动配置。

在 monorepo 场景下,如果你需要从其他目录解析配置,可以显式指定:

UniManifest({ cwd: resolve(__dirname, 'packages/h5') })

FAQ

这个插件写入配置晚于 uni-app 读取配置,导致无法正常运行

根因@dcloudio/vite-plugin-uni 在 Vite 的 config 钩子里通过 parseManifestJsonOnce 读取 manifest.json,而本插件在更晚的 configResolved 钩子里才写入。config 早于 configResolved,所以即便本插件设置了 enforce: 'pre',也只能在 configResolved 内部抢先,无法早于 config 钩子。parseManifestJsonOnce 结果被 once 缓存,首次读取后即固定,后续写入对 uni-app 无效。

核心矛盾是时序:必须在 uni-app 进程启动前把 manifest.json 生成好。以下按推荐度排序给出方案。

方案一(推荐):使用 @uni-helper/unh

unh 在调用 uni dev/build 前用 unconfig 加载 manifest.config.ts 并写盘,再 spawn 子进程,天然解决时序问题。

// package.json
{
  "scripts": {
    "dev": "unh dev",
    "build": "unh build"
  }
}
// unh.config.ts
import { defineConfig } from '@uni-helper/unh'

export default defineConfig({
  autoGenerate: {
    manifest: true, // 在 dev/build 前自动生成 manifest.json
  },
})

方案二:自行编写脚本,在 uni 命令前生成

用一个独立脚本加载 manifest.config.ts、写入 src/manifest.json,再用 && 串联到 uni 命令前。脚本在 uni 进程之外运行,与 Vite 钩子时序无关。

pnpm i -D c12 tsx
// scripts/generate-manifest.ts
import { loadConfig } from 'c12'
import { writeFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'

// 与本插件内部实现保持一致:c12 + defaultConfig 合并
const defaultManifestConfig = defineManifestConfig({
  // ...参考本插件 defaultManifestConfig,或按需精简
})

const { config } = await loadConfig({
  cwd: process.cwd(),
  name: 'manifest',
  defaultConfig: defaultManifestConfig,
  rcFile: false,
  packageJson: false,
})

// UNI_INPUT_DIR 由 vite-plugin-uni 注入,独立脚本中不可用,这里硬编码默认输入目录
// monorepo 或自定义 input dir 时改为对应路径
const outPath = resolve(process.cwd(), 'src/manifest.json')
writeFileSync(outPath, JSON.stringify(config, null, 2))
// package.json
{
  "scripts": {
    "dev:h5": "tsx scripts/generate-manifest.ts && uni",
    "build:mp-weixin": "tsx scripts/generate-manifest.ts && uni build -p mp-weixin"
  }
}

说明:manifest.config.ts 中的热更新监听在本方案下不生效——脚本只生成一次。开发期间修改 manifest.config.ts 需重新执行脚本(或重启 dev server)。本插件仍可作为 Vite 插件保留,用于处理 manifest.config.ts 的运行时变更;首次启动的正确性由本脚本兜底。

方案三:用 npm predev/prebuild 钩子

// package.json
{
  "scripts": {
    "predev": "tsx scripts/generate-manifest.ts",
    "prebuild": "tsx scripts/generate-manifest.ts",
    "dev": "uni",
    "build": "uni build"
  }
}

说明:npm 会在执行 dev/build 前自动运行同名 pre* 脚本。pnpm 10 同样会运行用户自定义的 predev/prebuild(注意 enable-pre-post-scripts 只影响 install 阶段的生命周期脚本,不影响 run 时的 pre*/post*)。比方案二的 && 串联更隐式,开发者可能意识不到 predev 被自动触发,排查问题时需额外留意,故排序靠后。

开发

前置条件

常用命令

# 安装依赖(在 monorepo 根目录执行)
pnpm install

# 构建所有包
pnpm build

# 仅构建 core 包
pnpm -C packages/core build

# 运行测试(在 monorepo 根目录执行)
pnpm test

# 类型检查
pnpm type-check

测试

测试文件位于 monorepo 根目录的 test/ 目录下,使用 Vitest 运行:

test/
├── options.test.ts     resolveOptions 默认值与合并
├── config.test.ts      defineManifestConfig 恒等函数
├── constant.test.ts    resolveManifestJsonPath + 默认配置结构
├── context.test.ts     ManifestContext 构造 + setup
├── writer.test.ts      writeManifestJson 格式化 + ensureManifestJsonExists
└── plugin.test.ts      插件工厂形状 + 生命周期

context.test.tsplugin.test.ts 使用 vi.mock 隔离 c12 和文件系统,确保测试不依赖真实环境。

项目结构

vite-plugin-uni-manifest/
├── packages/
│   ├── core/           插件核心逻辑
│   ├── types/          manifest.json TypeScript 类型定义
│   └── schema/         JSON Schema(从 types 自动生成)
├── test/               测试文件
├── playground/         示例 uni-app 项目
└── pnpm-workspace.yaml

架构

插件由四个职责清晰的模块组成:

index.ts          Vite 插件入口,组装各模块
context.ts        ManifestContext — 配置监听生命周期(c12 watchConfig)
writer.ts         文件 I/O — writeManifestJson / ensureManifestJsonExists
constant.ts       路径解析 — resolveManifestJsonPath + 默认配置
config/index.ts   defineManifestConfig 辅助函数 + 类型重导出
options.ts        resolveOptions — 合并用户选项与默认值

模块依赖关系

index.ts
  ├─ context.ts ── writer.ts ── constant.ts (resolveManifestJsonPath)
  │                │
  │                └── options.ts
  └─ writer.ts

插件生命周期

插件通过 Vite 的生命周期钩子驱动,顺序如下:

  1. configResolved(异步)— 确保 manifest.json 存在 → 创建 ManifestContext → 调用 setup() 启动 c12 监听
  2. 运行时 — c12 检测到 manifest.config.ts 变更 → onUpdate 回调 → writeManifestJson() 写入文件
  3. buildEnd — 调用 unwatch() 停止 c12 监听

关键设计决策

  • 无导入时副作用:所有文件系统操作(路径解析、文件写入)都在插件生命周期内执行,而非模块导入时。这使得模块可独立测试。
  • 路径解析为函数resolveManifestJsonPath() 每次调用重新计算路径,依赖 process.env.UNI_INPUT_DIR(由 @dcloudio/vite-plugin-uni 注入),不缓存。
  • c12 配置加载:通过 c12watchConfig 实现 manifest.config.ts 的监听和热更新,支持 .ts.mts.js.json 等格式。