@charcuterie/vite-config

中文文档
1.1.0发布于 2026/08/13MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 1806

A shared Vite config factory for the Charcuterie fleet — call createViteConfig(overrides) and add your own plugins.

原始使用文档

@charcuterie/vite-config

A shared Vite config factory for the Charcuterie fleet. Ships the build/server defaults every app wants and leaves plugins to the caller, so one preset serves a React SPA, an Electron renderer, and a library build.

Usage

// vite.config.ts
import { createViteConfig } from "@charcuterie/vite-config"
import react from "@vitejs/plugin-react"

export default createViteConfig({
  plugins: [react()],
  build: { outDir: "dist/web" },
})

Overrides are deep-merged over the base via Vite's own mergeConfig. Apps with multiple targets (e.g. image-viewer's Electron main/preload/renderer) call it once per target with different overrides.

vite is a peer dependency — the app owns the Vite version; Renovate bumps this package's range fleet-wide when the shared defaults change.

The index.html guard

The base ships one plugin, charcuterie:no-shadowed-injection-anchors, and it is not opt-in. It fails the build — and the dev server, at startup — when a structural tag literal sits inside an HTML comment before the real tag it shadows.

Vite finds its script-injection points with plain regexes over the raw HTML (/<head[^>]*>/i and siblings for </head>, <body>, </body>, </html>). They are comment-blind, so the first literal <head> in the file wins even inside <!-- … -->, and everything Vite meant to inject lands in the comment where the browser never parses it. In dev that is @vitejs/plugin-react's react-refresh preamble and /@vite/client: the console says "@vitejs/plugin-react can't detect preamble", $RefreshReg$ is undefined, HMR is dead, and the page is blank.

Production builds are unaffected, which is exactly why this needs a mechanism. typecheck, lint, unit-tests, e2e, build-budget and storybook-build all stay green while yarn dev serves nothing. It shipped twice, six days apart — image-viewer on 2026-08-05 (whose Locked decision record reached nobody else) and mux-magic on 2026-08-11 (#200) — which is what moved it into the shared build seam instead of a twelfth copy of the same paragraph.

[@charcuterie/vite-config] packages/web/index.html would break the dev server.

  line 10: a literal `<head>` inside an HTML comment comes before the real one
    the `@charcuterie/tokens` `buildFirstPaintScript` snippet in <head> below,
  …
  Fix: drop the angle brackets in the prose (`head`, not `<head>`), or
  move the comment below the real tag. Both are one line.

Three things about its scope are deliberate:

  • "Before the real tag", not "never in a comment". mux-magic's shipped fix keeps the word <head> in its comment — it moved the comment inside <head>, so the first literal in the file is now the real element. That file is correct and a blanket ban would fail it. The condition checked is Vite's actual failure condition, so the rule is exactly as strict as the bug.
  • Open <html> is not an anchor. Vite has no head-of-html injection point, so image-viewer's leading comment naming `<html>` shadows nothing and passes.
  • It runs in build as well as serve. Production is unaffected by the bug, so a serve-only check would leave CI exactly as blind as it was both times this shipped.

It fires in two hooks: configResolved reads index.html (and any HTML rollup input) off disk so yarn dev dies at startup with the reason printed, and transformIndexHtml (order: "pre") catches the served document. A check that only ran on the first request would let the server come up looking healthy — which is the exact experience being fixed.

The pure half is exported for anything that wants to check HTML without a Vite config:

import { findShadowedInjectionAnchors } from "@charcuterie/vite-config"

findShadowedInjectionAnchors(html)
// [{ anchor: "<head>", line: 10, snippet: "…snippet in <head> below," }]

An app that builds its Vite config by hand can add createStructuralTagCommentGuard() to its own plugins.

版本与发布记录

@charcuterie/vite-config 共发布 4 个版本,首次发布于 2026/08/08;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.1.0latest2026/08/132 个月前
1.0.22026/08/112 个月前
1.0.12026/08/083 个月前
1.0.02026/08/083 个月前

关于 @charcuterie/vite-config 的常见问题

@charcuterie/vite-config 是什么?

A shared Vite config factory for the Charcuterie fleet — call createViteConfig(overrides) and add your own plugins.

如何安装 @charcuterie/vite-config?

在项目目录运行 npm install @charcuterie/vite-config,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:vite(>=5)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@charcuterie/vite-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@charcuterie/vite-config 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@charcuterie/vite-config 可以商用吗?

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

@charcuterie/vite-config 的下载量有多少?

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

@charcuterie/vite-config 还在维护吗?

最新版本 1.1.0 发布于 2026/08/13(2 个月前);至今共发布 4 个版本,其中过去 12 个月发布了 4 个;首次发布于 2026/08/08。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。