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

@eason627/single-html-builder

v0.1.17

Published

Build a previewable HTML bundle for Vite Vue or React projects opened via file://

Readme

@eason627/single-html-builder

为 Vite 项目生成可直接双击打开的预览 HTML,适用于 file:// 场景下的本地预览与交付。

安装

npm i -D @eason627/single-html-builder

安装后会自动尝试在业务项目的 package.json 中注入:

  • scripts.build:single
  • scripts.build:single:web
  • singlePreviewBuilder 默认构建对象

如果你不想依赖自动注入,也可以手动添加:

{
  "scripts": {
    "build:single": "vite-single-preview-builder",
    "build:single:web": "vite-single-preview-builder --template web-folder --yes"
  },
  "singlePreviewBuilder": {
    "template": "single",
    "framework": "auto",
    "outDir": "dist",
    "publicDir": "public",
    "outputDir": ".",
    "outputFile": "【双击预览】.html",
    "assetMode": "smart",
    "inlineAssetMaxSize": 262144,
    "inlineAssetExtensions": [".css", ".js", ".mjs", ".svg", ".woff", ".woff2", ".ttf", ".eot", ".otf", ".ico", ".json"],
    "externalAssetDir": "【双击预览】_assets",
    "downloadedAssetDir": "external-assets",
    "downloadedAssetMode": "inline",
    "sourceRoots": ["index.html", "src", "public"],
    "cleanupTrash": false,
    "cleanupRoot": ".",
    "webDirectory": "web",
    "trashDirectoryNames": ["node_modules", "dist", "out", "build", ".next", ".nuxt", ".output", "coverage", ".vite", ".cache", ".cursor", ".claude", ".codex", ".vscode", ".git", ".codegraph"]
  }
}

用法

执行:

npm run build:single

如需使用图片中的交付结构,即当前目录下最终只保留 【双击预览】.htmlweb/ 项目目录,可执行:

npm run build:single:web

等价于:

npm run build:single -- --template web-folder --yes

执行后会先在命令行输出本次构建的关键信息:

  • 当前识别到的框架
  • 当前选择的打包模板
  • 入口文件
  • 路由文件
  • 资源目录
  • 扫描范围
  • 构建产物目录
  • 预览输出目录
  • 输出文件名
  • 资源模式
  • 图片等资源内联阈值
  • 外置资源目录
  • 资源物理输出目录
  • 下载资源目录
  • 下载资源处理方式
  • 垃圾目录清理状态
  • 垃圾目录约束名单
  • 待下载的外部资源 URL

随后会询问:

是否将下载的外链资源以内联 data: 方式打包进去?(y/n,默认 y)
  • 输入 y:仅将下载到本地的外链资源尽量转成 data: 内联进最终 HTML
  • 输入 n:下载资源保留文件引用,最终 HTML 可能引用输出资源目录中的文件路径

选择 n 时,命令行会额外提示你:

  • 需要同时移动预览 HTML 和资源目录
  • 建议在 package.json 中显式配置 outputDirexternalAssetDir

确认无误后按回车,才会正式开始打包。

默认行为

默认流程如下:

  1. 本地化外部资源
  2. 单文件模式构建
  3. 智能处理资源并输出预览 HTML

默认情况下:

  • 打包模板:single
  • 构建产物目录:沿用 Vite 原本配置,未配置时通常为 dist/
  • 预览输出目录:项目根目录
  • 单文件预览页:【双击预览】.html
  • 公共资源目录:public/
  • 资源扫描范围:index.htmlsrcpublic
  • 资源模式:smart
  • 下载资源目录:external-assets
  • 外置资源目录:【双击预览】_assets
  • 资源物理输出目录:默认跟随 outputDir
  • 体积超过 256 KB 的图片、音视频等资源默认不会继续内联进 HTML,而是输出到资源目录
  • 默认不清理垃圾目录;如需清理,必须显式传入 --clean-trash 或配置 cleanupTrash: true

打包模板

当前支持两种模板:

  • single:默认模板,在当前业务项目目录输出 【双击预览】.html,保持旧流程不变
  • web-folder:图片结构模板。先在当前目录产出 【双击预览】.html,再清理垃圾目录,最后创建 web/ 并把除 HTML 外的文件移动进去,最终结构类似:
合作伙伴管理系统/
├─ 【双击预览】.html
└─ web/
   ├─ public/
   ├─ src/
   ├─ index.html
   ├─ package.json
   └─ vite.config.ts

web-folder 模板默认会启用 assetMode: "smart"assetOutputDir: "web"cleanupTrash: truewebDirectory: "web"。整理顺序固定为:构建 HTML,把外置大资源输出到 web/【双击预览】_assets,重新扫描并清理垃圾目录,再将除 【双击预览】.htmlweb/ 外的所有文件、目录移动到 web/。移动时遇到同名目标会停止,避免覆盖已有内容。

如果强制使用 assetMode: "inline-all",图片、字体、音视频等二进制资源会被转成 base64 写进 HTML,体积通常会额外膨胀约三分之一;同时本工具还会处理 public/ 和项目根目录静态资源,不只处理 dist/,因此 HTML 可能远大于原始 dist/ 目录。

如果执行 npm run build:single:web 后仍然出现资源内嵌询问、【双击预览】_assets 或未清理目录,请先检查业务项目 package.json 中脚本是否仍是旧值。新脚本应为:

{
  "scripts": {
    "build:single:web": "vite-single-preview-builder --template web-folder --yes"
  }
}

CMD 参数

可通过以下方式把参数透传给命令:

npm run build:single -- --template web-folder --yes

可选参数:

  • --template <single|web-folder>:选择打包模板
  • --output-dir <dir>:覆盖预览 HTML 输出目录
  • --output-file <file>:覆盖预览 HTML 文件名
  • --asset-mode <smart|inline-all>:覆盖资源处理模式
  • --inline-asset-max-size <bytes>:覆盖 smart 模式资源内联阈值
  • --downloaded-asset-mode <inline|file>:覆盖下载资源处理方式
  • --scan-trash:扫描并列出可清理的垃圾目录,不删除文件
  • --clean-trash:构建成功后清理垃圾目录
  • --yes:使用默认确认项直接开始构建,适合 CI 或自动化脚本
  • --help / -h:显示命令帮助

垃圾目录清理

打包命令可以在 CMD 中扫描并列出可清理的垃圾目录:

npm run build:single -- --scan-trash

构建成功后自动清理:

npm run build:single -- --clean-trash

清理有明确约束:

  • 默认只扫描 cleanupRoot 的直接子目录,cleanupRoot 默认是当前业务项目目录 .
  • 只处理 trashDirectoryNames 约束名单里的目录名
  • 默认约束名单:node_modulesdistoutbuild.next.nuxt.outputcoverage.vite.cache.cursor.claude.codex.vscode.git.codegraph
  • 不会递归查找同名目录,避免误删源码内部目录
  • 如果目录正好是本次配置的 outputDirassetOutputDir,会自动从清理候选中排除
  • --scan-trash 只打印扫描结果,不删除
  • --clean-trash 只在完整构建成功后执行删除;构建失败不会清理
  • cleanupRoot 必须位于项目目录内,超出项目目录会跳过清理

如需调整名单,可在业务项目 package.json 中配置:

{
  "singlePreviewBuilder": {
    "cleanupTrash": false,
    "cleanupRoot": ".",
    "webDirectory": "web",
    "trashDirectoryNames": ["node_modules", "dist", "out", "build", ".next", ".nuxt", ".output", "coverage", ".vite", ".cache", ".cursor", ".claude", ".codex", ".vscode", ".git", ".codegraph"]
  }
}

自动识别

当前版本会自动识别项目环境,尽量做到零配置可用:

  • 自动识别 vue / react
  • 自动识别常见入口文件
  • Vue 项目自动识别常见路由文件
  • 自动扫描源码中的外部资源引用
  • 自动下载并本地化外链 CSS、字体、图片等资源
  • 最终优先内联关键资源,并自动拆分体积过大的静态资源,避免单文件产物失控

Vue 项目常见入口识别优先级:

  • src/main.ts
  • src/main.js
  • src/main.mts
  • src/main.mjs
  • src/main.tsx
  • src/main.jsx

React 项目常见入口识别优先级:

  • src/App.tsx
  • src/App.jsx
  • src/App.ts
  • src/App.js
  • src/main.tsx
  • src/main.jsx

配置

大多数项目不需要配置,零配置即可使用。

如需覆盖默认行为,可在业务项目 package.json 中增加:

{
  "singlePreviewBuilder": {
    "template": "single",
    "framework": "vue",
    "appEntry": "src/main.ts",
    "routerEntry": "src/router/index.ts",
    "outDir": "dist",
    "publicDir": "public",
    "outputDir": ".",
    "outputFile": "【双击预览】.html",
    "assetMode": "smart",
    "inlineAssetMaxSize": 262144,
    "inlineAssetExtensions": [".svg", ".woff2", ".woff", ".ttf", ".css", ".js"],
    "externalAssetDir": "【双击预览】_assets",
    "assetOutputDir": ".",
    "downloadedAssetDir": "external-assets",
    "downloadedAssetMode": "inline",
    "sourceRoots": ["index.html", "src", "public"],
    "cleanupTrash": false,
    "cleanupRoot": ".",
    "webDirectory": "web",
    "trashDirectoryNames": ["node_modules", "dist", "out", "build", ".next", ".nuxt", ".output", "coverage", ".vite", ".cache", ".cursor", ".claude", ".codex", ".vscode", ".git", ".codegraph"]
  }
}

配置项说明:

  • template: 打包模板,可选 singleweb-folder,默认 single
  • framework: 指定框架,可选 vuereactauto,默认 auto
  • appEntry: 指定应用入口文件
  • routerEntry: 指定路由文件,当前主要用于 Vue Router 场景
  • outDir: 指定构建产物目录;如果不填,优先沿用业务项目的 Vite 配置
  • publicDir: 公共资源目录,默认 public
  • outputDir: 预览 HTML 的输出目录,默认项目根目录
  • outputFile: 最终预览文件名称,默认 【双击预览】.html
  • assetMode: 资源处理模式,默认 smart;可选 smartinline-all
  • inlineAssetMaxSize: 智能模式下的内联阈值,默认 262144
  • inlineAssetExtensions: 始终优先内联的扩展名列表
  • externalAssetDir: 非内联资源的输出目录,默认 【双击预览】_assets
  • assetOutputDir: 资源物理输出目录,默认跟随 outputDir;如需把资源留在项目原目录,可显式设为 .
  • downloadedAssetDir: 识别“下载的本地资源”所用的目录名,默认 external-assets
  • downloadedAssetMode: 下载资源默认处理方式,默认 inline;运行时可通过命令行 y/n 临时覆盖
  • sourceRoots: 扫描外部资源引用的根路径列表
  • cleanupTrash: 是否在构建成功后清理垃圾目录,默认 false
  • cleanupRoot: 垃圾目录扫描根路径,默认 .
  • webDirectory: web-folder 模板整理源码时使用的目录名,默认 web
  • trashDirectoryNames: 允许清理的垃圾目录名约束名单

兼容说明

当前版本重点兼容以下场景:

  • Vite + Vue
  • Vite + React
  • Next.js 静态导出产物
  • Vue Router 本地预览
  • React Router 本地预览
  • 外链 CSS / 字体 / 图片资源的本地化与处理
  • 大图片资源自动拆分,避免最终 HTML 体积过大

当前版本不直接支持:

  • 非 Vite 构建体系
  • Next.js SSR / 服务端运行模式
  • 未开启 output: 'export' 的 Next.js 项目

注意事项

  • 建议在发布前先执行一次 npm run build:single 本地验证最终 HTML
  • 如果页面存在大量图片、视频、音频资源,建议保持默认 smart 模式
  • 如果输入 n,最终预览文件不再是绝对单文件,必须和 externalAssetDir 一起移动
  • 如果你计划把 HTML 输出到别处、但资源仍留在项目原目录,可显式配置 outputDirassetOutputDir
  • inline-all 更适合纯演示页或资源很少的页面,不适合包含大量素材的业务系统
  • 如果业务项目中存在大量运行时动态加载资源,仍需单独确认这些资源是否能在 file:// 场景下工作
  • 若业务项目使用了非常规入口结构,建议显式配置 appEntryrouterEntry
  • 若你升级了包但没有看到新行为,请确认业务项目里安装的是最新版本依赖