一、前言
在日常的开发中,我们经常会遇到这样的场景:
- 有些可复用的工具包或组件,可抽象成公共代码,供小组内部成员共同维护和使用
- 业务组件需要提供给外部合作方使用
- .....
npm包即以上需求的通用解决方案之一。npm作为Node.js平台的默认包管理工具,可以实现安装、共享、分发代码。(通常不同公司内部有私有的npm服务器)
本文记录本人在开发一个npm包时,会遇到的一些常见问题。
二、n件事
package.json
命名
name字段:遵循semantic规范 详情
正式版本:1(major).0(minor).0(patch),预览版本:1.0.0-prefix.x
patch:错误修复,可向后兼容
minor:次要版本,新功能,可向后兼容
major:大版本迭代,不兼容的更改
导出相关
-
main字段->node.js消费,指定加载文件入口;
-
module字段-> bundler打包器消费,esm版本,支持tree-shaking;
-
types-> 供ts 以及 ide消费;
-
exports:定义模块的导出,import路径 与 产物路径 的对应关系
- 与main若共存,优先使用exports
-
files:字段是一个用于指定在发布
npm包时应该包含哪些文件或目录的数组
main字段指向的文件应该在files指定的文件范围内。如果main指向的文件不在files指定的文件中,当这个包被安装到其他项目时,可能会出现找不到入口文件的情
files字段可以用来确保只发布必要的文件,并且可以通过配置确保main所依赖的其他文件(如辅助函数文件、配置文件等,如果它们在main文件中被引用)也被包含在发布的包中。例如,如果main文件lib/index.js依赖于lib/utils.js,那么可以通过"files":["lib/*"]确保这两个文件都被发布。
依赖相关
与依赖相关的不同字段的区别:
- dependencies:生产环境必需的依赖,如express作为服务器请求库;
- devDependencies:开发环境所需的依赖,在项目运行中不需要,如测试框架jest,构建工具webpack等;
- peerDependencies:可由包的使用者或宿主环境提供的依赖,避免依赖的重复安装,如react,react-dom,一般在组件库的使用项目中,已安装对应依赖;
- resolutions:主要用于解决依赖冲突的问题,当不同的依赖包依赖同一个库的不同版本时,使用resolutions指定版本,避免版本冲突
-
依赖版本号:参考
-
~/^
-
~ 从右往左匹配非0
-
^ 从左往右开始匹配非0
-
bin
- bin:指定可执行的命令脚本,当你的项目被全局安装(
npm install -g)或者本地安装后在node_modules/.bin下被调用时,bin字段定义的命令就可以被执行。常用来做自动化工具。
脚本文件:路径 ./bin/index.js
开发包 @package/utils-cli
#!/usr/bin/env node
import '../dist/es/index.js';
在bin字段中注册命令
"bin": {
"utils-cli": "./bin/index.js"
},
使用:
- 局部安装:在使用方的package.json下安装依赖+注册脚本
{
"name": "utils-mono",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
......
"create": "utils-cli init"
},
......
"devDependencies": {
对应工具依赖
"@package/utils-cli": "0.0.0-feat-test-20240825022141",
},
}
- 全局安装:
命令行直接输入 utils-cli init
编译
将一种语言编写的源代码转换为另一种语言的过程。
-
现有编译工具:
- babel:新版本js->旧版本(浏览器兼容),ts->js等
- tsc:ts官方编译器,ts->js
- swc
- esbuild
构建打包
将开发环境的代码,转换为生产环境的代码,通常通过合并,压缩,转换(存在高级语法),使得转换后的源码可在不同环境中使用。
-
现有模块打包工具:
- webpack:静态模块打包工具,从一个或多个入口点构建一个依赖图;
- esbuild:用go编写,快;
- rollup
- Parcel
- Vite
- ......
-
方案:bundle 与bundleless
-
bundle:传统的编译打包方案,常用工具有webpack,rollup等。
-
bundleless:无构建形式,常用工具有vite,snowpack等。
- 出现bundleless的背景:
-
由于项目资源增长与代码膨胀,构建的速度越来越慢,项目本地启动缓慢,更新缓慢,影响开发体验;
-
浏览器原生支持esm模块,type="module",可实现、直接获取文件在浏览器上运行;
-
- 出现bundleless的背景:
-
monorepo下的包版本管理
-
解决问题:多包管理,各包之间互相依赖
- npm link的作用:将当前某个具体包在全局文件夹下创建一个符号链接,在其他使用方包下,再创建一个从全局链接到当前node_module的符号链接。
- 缺点:两步操作,多个子包操作复杂性,有依赖关系时,需要确定执行命令的先后顺序;版本更新麻烦。
-
- lerna
- npm/yarn/pnpm +changeset
- changeset 版本管理和发布,包含在分支与commit山的改动信息的markdown文件, init->add->version->publish
发包
- 传统发包流程:
原始:npm init 生成 npm模版, 编写代码,commit,手动变更版本号 , npm publish,git push
辅助npm工具:
npm version 版本升级,自动打tag
conventional-changelog 根据规范commit自动生成版本变更内容CHANGELOG.md
standard-version 取代npm version命令,根据commit message自动决定下一个版本号
semantic-release CI发包