用 pnpm 发包时怎么指定入口文件?
我最近用 pnpm 开发了一个 React 组件库,本地测试没问题,但发布到私有 npm 仓库后,别人安装使用时报错说找不到模块。我怀疑是 package.json 里的入口配置不对,但不确定该改 main 还是 module 字段。
我的组件代码大概是这样的:
import React from 'react';
const MyButton = ({ children }) => {
return <button className="my-btn">{children}</button>;
};
export default MyButton;
现在 package.json 里只写了 “main”: “dist/index.js”,但构建后的文件还有 esm 格式的。是不是还得加 exports 或 module 字段?pnpm 和 npm 在这方面有区别吗?
先说结论:你只配了 main 字段,但构建产物有 esm 格式,别人用的时候 bundler(webpack/vite/rollup 之类的)可能去读 module 字段或者 exports 字段,结果找不到对应文件,就报错了。
入口文件配置的几个关键字段
main - CommonJS 格式入口,node require() 调用时用
module - ESM 格式入口,import 语句调用时用
exports - 更现代的导出方式,可以根据环境(node、import、require)指定不同入口
types - TypeScript 类型定义文件
pnpm 和 npm 的区别
pnpm 这边有个坑:它对 node_modules 的处理比 npm 严格太多了。npm 会把依赖平铺到项目根目录,pnpm 用符号链接的方式把依赖放到 store,然后在项目里创建虚拟目录。
这个设计导致一个问题:如果你的 package.json 里的入口文件路径写错了,或者字段不全,pnpm 解析起来比 npm 更容易出问题。特别是当你用 exports 字段的时候,pnpm 要求更严格。
解决方案
假设你用 vite 或者 rollup 构建,应该生成了类似这样的目录结构:
那么你的 package.json 应该这样配:
解释一下 exports 字段为什么这样写:
- "." 表示包的根入口
- types 放最前面,TypeScript 会优先读取
- import 对应 ESM 环境
- require 对应 CommonJS 环境
这样配置完,不管别人用哪种方式导入都能正确找到文件。
额外提醒
检查一下你的构建配置,确保 dist 目录下的文件名和 package.json 里写的对得上。如果你用的是 TypeScript,记得确认 tsconfig 里的 outDir 设置和实际输出一致。
还有一点,pnpm 默认会读取 package.json 里的 sideEffects 字段(如果有的话),如果你组件库没有副作用,可以加上
"sideEffects": false,这样 tree-shaking 效果更好。你先按这个配置改一下试试,有问题再贴具体报错信息。