1. 为什么一个TS库的打包值得单独拿出来说如果你写过一段时间TypeScript大概率经历过这个阶段本地开发爽得不行类型提示、自动补全、重构跳转全都到位结果一到“要给别人用”的时候就开始犯难。代码是TS写的但用的人可能是JS项目也可能是TS项目还可能是在Node环境跑也可能是在浏览器里跑。你总不能要求所有人都装一套TS编译环境再来用你的库吧。所以一个成熟的TypeScript库交付物通常得同时满足两件事一份能直接跑的JavaScript文件以及一份能让TS使用者继续享受类型提示的声明文件.d.ts。这两样东西缺一个库的可用性就打了折扣。只给JSTS用户体验断崖式下跌只给类型没有可执行产物那更是空中楼阁。这个项目标题说的就是这件事用rollup把TypeScript库打包输出JS文件加类型声明文件。听起来像是个“配置一下就行”的活儿但我实际折腾下来里面的坑比想象中多。比如声明文件到底怎么生成、rollup的插件顺序怎么排、输出格式选哪几种、package.json里的字段怎么配才能让各种模块系统都认这些细节但凡有一个没处理好使用者就会在引入你的库时遇到莫名其妙的报错。这篇文章适合两类人看一类是刚写完自己的第一个TS库、准备发布出去的新手另一类是已经能打包但总在类型声明或模块格式上翻车的朋友。我会从整体设计思路讲起把rollup配置、TypeScript编译、声明文件生成、产物验证这几个环节拆开揉碎配上可直接抄的配置和踩坑记录。读完你至少能做到打包产物干净、类型声明完整、各种引入方式都不报错。2. 整体方案设计与工具选型考量2.1 为什么是rollup而不是别的打包器先说说选型这件事。打包TS库的工具其实不少webpack、esbuild、tsup、rollup都能干。我最终倾向rollup核心原因在于它对库library场景的定位更纯粹。webpack更偏向应用打包配置里一堆跟资源处理、devServer相关的东西对纯库来说太重esbuild速度快得惊人但它在类型声明生成这块需要额外配合生态上不如rollup成熟tsup本质上是rollup的封装省事但黑盒出了问题排查起来隔了一层。rollup的设计哲学是“只做打包这一件事”配合插件体系可以精确控制每一步。对于库作者来说这种可控性很重要——你需要清楚地知道哪些代码进了产物、哪些被tree-shaking掉了、外部依赖有没有被误打进去。而且rollup对ESM的原生支持非常好输出格式灵活这对一个要同时兼容多种模块系统的库来说是刚需。当然选rollup也意味着你要自己把TypeScript编译和声明文件生成这两块拼起来不像tsup那样开箱即用。但这个“拼”的过程恰恰是理解整个链路的机会配一次之后心里就有底了。2.2 输出格式的取舍ESM、CJS还是都要模块格式的选择直接决定了谁能用你的库。现在的主流趋势是ESM但现实是大量存量项目还在用CommonJS尤其是Node端的工具类库。我的建议是至少同时输出ESM和CJS两种格式成本不高但覆盖面广。具体到配置上rollup的output.format可以设成es和cjs分别对应.mjs或.js配合type: module和.cjs。这里有个细节如果你的package.json里写了type: module那.js文件会被当成ESMCJS产物就得用.cjs后缀反过来如果没写type.js默认是CJSESM产物用.mjs。我一般倾向于不设type: module然后用.mjs和.cjs明确区分这样最不容易混淆。至于UMD格式除非你的库明确要给浏览器script直接引入用否则没必要加。多一种格式就多一份维护成本和测试负担而且UMD在tree-shaking上表现不佳。2.3 声明文件生成的两种路线类型声明文件的生成有两条主流路线得先想清楚走哪条。第一条是用TypeScript自带的declaration: true让tsc在编译时顺带产出.d.ts。这条路线的好处是类型绝对准确因为就是编译器自己吐出来的缺点是它和rollup的打包流程是分离的你需要么先跑tsc再跑rollup要么用rollup-plugin-typescript2这类插件把两者串起来。第二条是用rollup-plugin-dts先把TS编译成JS此时可能已经带了声明再用这个插件把散落的.d.ts合并成单个声明文件。它适合产物需要“单文件声明”的场景比如你的库对外只暴露一个入口。我实际用下来比较稳的组合是用rollup-plugin-typescript2负责编译TS并生成声明再用rollup-plugin-dts把声明合并成单文件。这样既有编译器的准确性又有单文件声明的整洁。如果库的入口结构简单其实光靠tsc生成声明也够用看个人对产物形态的要求。2.4 外部依赖的处理原则库和应用打包有个根本区别库不应该把自己的依赖打进去。比如你的库用了某个工具函数包这个包应该作为peerDependencies或dependencies声明在package.json里让使用者的包管理器去解析而不是被你塞进产物里造成重复。在rollup里对应的就是external配置。所有dependencies和peerDependencies里的包都应该被标记为external这样rollup不会尝试解析和打包它们。我见过有人忘了配这个结果产物里嵌了一整个依赖库使用者装了两个版本行为诡异还查不出原因。这个坑后面还会细说。3. 核心配置拆解与关键参数说明3.1 目录结构与入口约定动手写配置前先把目录结构定下来。我习惯的布局是这样的源码放src/入口文件是src/index.ts产物输出到dist/。dist/里最终会有index.mjs、index.cjs以及index.d.ts如果做单文件声明的话。tsconfig.json里几个关键项要留意。target建议设成ES2018或更高太老的target会让编译产物里塞一堆辅助函数module设成ESNext把模块转换的活儿交给rollupdeclaration设成truedeclarationDir指向dist/types之类的临时目录方便后续合并strict强烈建议打开库的类型质量直接影响使用者的体验。{ compilerOptions: { target: ES2018, module: ESNext, moduleResolution: node, declaration: true, declarationDir: dist/types, outDir: dist, strict: true, esModuleInterop: true, skipLibCheck: true }, include: [src] }这里skipLibCheck: true能跳过对声明文件本身的类型检查加快编译速度对库项目来说一般没副作用。esModuleInterop打开后import默认导入的写法更符合直觉建议开。3.2 rollup配置文件逐段解析rollup的配置我一般写成rollup.config.mjs用ESM语法清晰。核心结构是一个数组每个元素对应一种输出格式的配置或者拆成“编译”和“声明合并”两个独立任务。先看编译任务。插件顺序很关键typescript2要在nodeResolve和commonjs之前因为它负责把TS转成JS后面的插件处理的是转换后的模块解析。nodeResolve用来解析第三方依赖虽然库场景下大部分依赖被external了但有些内联的小工具可能需要commonjs用来把CJS模块转成ESM供rollup处理。import typescript from rollup-plugin-typescript2; import { nodeResolve } from rollup/plugin-node-resolve; import commonjs from rollup/plugin-commonjs; import dts from rollup-plugin-dts; const external [some-dep, another-dep]; export default [ { input: src/index.ts, external, output: [ { file: dist/index.mjs, format: es }, { file: dist/index.cjs, format: cjs, exports: named } ], plugins: [ nodeResolve(), commonjs(), typescript({ tsconfig: ./tsconfig.json, useTsconfigDeclarationDir: true }) ] }, { input: dist/types/index.d.ts, output: { file: dist/index.d.ts, format: es }, plugins: [dts()] } ];exports: named这个参数值得说一下。CJS输出时如果你的库用的是具名导出rollup默认可能会警告“mixing named and default exports”。加上exports: named明确告诉rollup按具名导出处理能消掉警告也让产物更规范。第二个配置块专门处理声明合并输入是tsc生成的dist/types/index.d.ts输出是单文件dist/index.d.ts。dts()插件会把所有引用到的类型声明内联进来最终得到一个自包含的声明文件。3.3 package.json里的字段怎么配才不翻车这块是重灾区。很多人打包产物没问题但使用者一引入就报错八成是package.json字段没配对。核心是main、module、types、exports这几个。main指向CJS产物module指向ESM产物这是打包器识别的非标准但广泛支持的字段types指向声明文件。exports字段则是现代Node的入口映射优先级最高配好了能精确控制不同条件下的入口。{ name: my-lib, version: 1.0.0, main: ./dist/index.cjs, module: ./dist/index.mjs, types: ./dist/index.d.ts, exports: { .: { types: ./dist/index.d.ts, import: ./dist/index.mjs, require: ./dist/index.cjs } }, files: [dist], sideEffects: false }exports里的顺序有讲究types必须放最前面否则某些TS版本解析时会找不到类型。import和require分别对应ESM和CJS引入。files字段限定发布内容只包含dist避免把源码和配置一起发出去。sideEffects: false告诉打包器这个库没有副作用可以放心tree-shaking对使用者友好。注意exports字段一旦配置就会“锁死”包的入口使用者不能再通过深层路径引入未在exports里声明的文件。如果你的库需要暴露子路径比如my-lib/utils记得在exports里一并声明否则会报“Package subpath not exported”。3.4 声明文件路径的常见错位一个高频问题是声明文件生成了但使用者的编辑器找不到类型。原因通常是types字段指向的路径和实际产物对不上。比如tsc把声明生成到了dist/types/index.d.ts但package.json里types写的是dist/index.d.ts中间差了一层目录。解决办法要么调整declarationDir让声明直接落在dist根下要么用rollup-plugin-dts合并后输出到dist/index.d.ts。我倾向后者因为单文件声明对使用者更友好也避免了声明文件里相对路径引用错乱的问题。合并时如果遇到“找不到模块”的报错检查一下dts()的输入路径是否和tsc实际输出路径一致这个路径错一位就全盘皆输。4. 完整实操流程与产物验证4.1 从零搭建的完整步骤假设你已经有了一
企业数字化 ERP 产品动态
相关推荐
基于AT89S52与DAC0832的0.1V步进数控直流电源设计 简介:这份资源面向参加全国电子设计大赛的学生及电子电路学习者,聚焦「D简易数控直流电源」赛题,提供一套完整的数字显示电路设计方案,帮助读者理解数控电源从原理到实现的整体思路。压缩包内共1个doc文档,约131KB&… · 2026/11/3 3:41:36
ESXi在vCenter显示未响应:心跳超时定位与pktcap-uw抓包排查 ESXi 主机在 vCenter 里突然变成灰色的“未响应”,同时告警邮件一封接一封地来,这件事凡是维护过虚拟化平台的人都遇到过。它最让人难受的地方不在于故障本身,而在于信息量极少:主机还活着没有?虚拟机还在跑没有&#… · 2026/11/3 3:41:36
Epicor交易类型码全解析:从业务事件到会计事件的映射与避坑指南 简介:面向 Epicor ERP 实施顾问、财务与成本会计及供应链运维人员,这份资料系统梳理了 Epicor 交易业务类型的编码含义与账务影响,帮助读者在库存、采购、生产、服务等模块中准确识别每笔交易对应的借贷科目与成本流转逻辑。压缩包内仅含 1 个… · 2026/11/3 3:41:36
无人机操作员认证培训全解析:市场需求与课程设计 1. 无人机操作员认证培训的市场需求分析最近两年,无人机应用场景呈现爆发式增长态势。根据行业调研数据显示,2023年国内商用无人机市场规模已突破500亿元,年增长率保持在30%以上。这种快速增长直接催生了对专业无人机操作员的海量需求&#x… · 2026/11/3 4:11:44
零基础PCB设计入门:从建库、原理图到DRC打样避坑 简介:这份PDF教程面向PCB设计零基础学习者,围绕嘉立创EDA的使用流程整理自学思路,适合希望建立规范工具习惯、系统补齐入门短板的学生、硬件爱好者与转岗人员,也可用于课程设计、电子制作前期准备等场景。内容按创建项目与元件库、… · 2026/11/3 4:11:44
Reverse-Skill:面向生产压力的技能健康度评估方法 1. 项目概述:这不是“逆向工程”的代名词,而是技能反向生长的系统方法论“reverse-skill”这个词乍看像技术黑话——有人第一反应是“逆向工程(Reverse Engineering)”,有人联想到渗透测试里的漏洞回溯,还有… · 2026/11/3 4:11:44
Python爬虫+MongoDB+Word导出政务数据完整链路 简介:本资源是一份面向Python初学者与Web数据采集实践者的完整技术文档,聚焦于网页爬虫开发与非关系型数据库存储的工程化落地。内容系统讲解如何使用requests库发起HTTP请求、BeautifulSoup或lxml解析HTML、正则表达式提取关键字段,并将结构… · 2026/11/3 4:11:44
Python打砖块实战:物理碰撞、子步长与实时循环调优 1. 为什么老游戏是练手的最佳题材某套入门课程讲到第 95 课的时候,突然插了一段几十年前的旧事:有个年轻人揣着一份简历去一家做街机的小公司应聘,人家问他会什么,他说“什么都会”,于是被留了下来,后来还真… · 2026/11/3 4:11:44
代码注释规范:避免多语言陷阱的技术实践 1. 项目背景与核心问题那天下午的代码评审会,整个技术部门都记得清清楚楚。新来的技术总监王总正对着投影屏幕皱眉,突然整个人僵在了那里——他面前的IDE里,密密麻麻全是西夏文注释的Java代码。会议室里鸦雀无声,只听见空调出风口… · 2026/11/3 4:10:43
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18