关键在于结构设计、exports声明、preservemodules配置及files白名单:需按子模块组织源码,用exports映射路径,vite开启preservemodules输出对齐结构,并在package.json中精确声明files和入口字段。

在 Vite 中以库模式(build.lib)打包并发布一个 npm 包,关键不是“怎么打包”,而是“怎么打包得可按需、可导入、可发布”。整个流程围绕 结构设计 → 构建配置 → 导出声明 → 发布准备 四个环节展开,缺一不可。
组件或函数库必须有清晰的模块化结构
不能只靠一个 index.ts 全量导出。用户按需引入(如 import Button from 'my-lib/button')的前提是:库本身提供对应路径的真实文件。
- 每个组件/工具函数单独组织为子目录,例如
src/button/index.ts、src/utils/debounce.ts - 每个子目录内导出组件主体 + 样式(如有),例如
export { default as Button } from './Button.vue'; export * as style from './Button.css'; - 根目录
src/index.ts只做全量导出(供兼容场景),不参与按需逻辑
package.json 必须正确声明 exports 和入口字段
exports 字段是现代 ESM 按需加载的基石,它告诉 Node 和构建工具:“哪些子路径合法、对应什么文件”。没有它,import 'my-lib/button' 会被视为无效路径。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 设置
"type": "module",确保项目默认走 ESM - 用
exports明确映射子路径,例如:"./button": { "import": "./dist/button/index.mjs", "require": "./dist/button/index.cjs" } - 保留传统字段兼容旧环境:
main(CJS 入口)、module(ESM 入口)、types(类型声明入口)
Vite 配置要启用 preserveModules 并分离输出格式
默认库模式会把所有代码打成单个 .mjs 文件,这和按需打包冲突。必须开启 preserveModules: true,让输出结构与源码结构对齐。
- 在
rollupOptions.output中配置多个输出目标,例如:
– ES 模块输出到es/目录,格式format: 'es',启用preserveModules: true
– CommonJS 输出到lib/目录,格式format: 'cjs',同样启用preserveModules -
external: ['vue', 'react']等运行时依赖必须显式排除,避免被打包进去 - 搭配
vite-plugin-dts自动生成.d.ts声明文件,否则 TS 用户无法获得类型提示
发布前检查文件白名单与样式注入策略
npm 发布只上传 files 字段列出的文件,漏掉 es/ 或 types/ 就会导致用户无法按需引入或无类型。
- 在
package.json中明确声明:"files": ["es", "lib", "types", "dist", "index.d.ts"] - 样式处理二选一:
– 若组件样式轻量且强耦合,用插件(如rollup-plugin-postcss)将 CSS 内联进 JS,省去用户手动import 'xxx/style.css'
– 若样式需独立提取(如主题切换),则保持 CSS 单独输出,并在exports中补上"./button/style": "./dist/button/style.css"
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










