最近在写一个eslint config
的整合包,因为有不同语言,会发多个 npm 包,通过 Lerna 来管理多包发布,它优化了使用 git 和 npm 管理多包存储库的工作流,Vue、Babel、React 都有使用 Lerna。这里记录下使用过程中的一些点。
¶一、两种工作模式
¶1.1、固定模式
Fixed/Locked mode,Vue,Babel 都是用这种,在 publish 的时候,会依据lerna.json
文件里面的"version": "0.0.1"
进行增加,只选择一次,其他有改动的包自动更新版本号。
¶1.2、独立模式
Independent mode,执行lerna init --independent
命令初始化项目,lerna.json
文件里面会设置"version": "independent"
。每次 publish 时,会得到一个提示符,提示每个已更改的包,以指定是补丁、次要更改、主要更改还是自定义更改(x.y.z
)。
¶二、初始化
新建一个文件夹eslint-config-liuxy0551
,并进入该文件夹;为了方便 github action,安装 lerna 到开发环境:
1 | npm init -y |
因为 lerna 经常需要用到,我们全局安装下:
1 | yarn global add lerna |
安装完成后输入lerna -v
查看版本号:
1 | lerna init |
我们使用固定模式,然后进入packages
文件夹初始化几个不同语言对应的 eslint config 包:
1 | cd packages |
项目结构如下:
1 | eslint-config-liuxy0551 |
按照约定 Shareable Configs,包名应该以eslint-config-
开头,例如:eslint-config-liuxy0551-basic
。依次将 packages 下的几个 package.json 中的 name 改成如:@liuxy0551/eslint-config-liuxy0551-basic,version 改成 0.0.0。
每个子 package 都有自己的 node_modules,通过如下设置,就可以只在根目录创建 node_modules,只有开启了 private 的项目才能使用 workspaces。依次修改根目录的 package.json 和 lerna.json,添加以下配置项:
1 | "private": true, |
1 | "useWorkspaces": true, |
¶三、绑定 git 和 npm
接下来与远程仓库绑定,并登录 npm:
1 | git remote add origin git@github.com:liuxy0551/eslint-config-liuxy0551.git |
1 | npm whoami |
注意
如果上述命令报错,排查 npm 源:npm config ls
设置 npm 官方源:npm config set registry https://registry.npmjs.org/
如果未登录则执行npm login
登录
¶四、配置内容
在 packages/basic 文件夹下新建 index.js,内容如下:
1 | module.exports = { |
rules
对象就是我们可以自己改动的配置项,在Airbnb/JavaScript
仓库中的 https://github.com/airbnb/javascript/issues/1089,告诉了我们有哪些规则可以被修改。
¶五、lerna 命令
¶5.1、创建一个包
lerna create <包名> [存放的目录]
1 | lerna create packageName |
¶5.2、查看当前列表
1 | lerna list |
¶5.3、增加本地或者远程 package 作为当前项目 packages 里面的依赖
lerna add [@version] [--scope=localPackageName] [-D] [--exact]
- -D 表示安装到 devDependencies
- –exact 表示安装准确版本,不带 ^
注意
以下基于node 12
版本安装插件,需要兼容低版本的可以在插件后加上版本号
1 | lerna add eslint |
1 | lerna add --scope=@liuxy0551/eslint-config-liuxy0551-basic eslint-loader |
加上--scope=
表示给本地指定的包安装依赖,也可以 cd 到这个包的文件夹下安装,就不用加--scope=
了;不加则是给所有子包都安装该依赖。
1 | lerna add --scope=@liuxy0551/eslint-config-liuxy0551-typescript @liuxy0551/eslint-config-liuxy0551-basic |
1 | lerna add --scope=@liuxy0551/eslint-config-liuxy0551-react @liuxy0551/eslint-config-liuxy0551-typescript |
1 | lerna add --scope=@liuxy0551/eslint-config-liuxy0551-prettier @liuxy0551/eslint-config-liuxy0551-react |
¶5.4、安装依赖
因为我们指定过使用 yarn,直接执行yarn install
就会把所有包的依赖安装到根目录的 node_modules。
1 | lerna bootstrap |
¶5.5、删除依赖
1 | lerna clean --scope=特定的某个包 |
和rm -rf node_modules
功能一致,--scope=
表示指定包,不会移除根目录的 node_modules。
¶5.6、建立软链接
lerna link [--force-local]
1 | lerna link --force-local |
类似npm link
的使用,–force-local 表示不论本地的版本是否符合,都使用本地的版本。
¶5.7、列出更新的包
1 | lerna changed |
列出改动过的包,发布时只更新改动过的包。
¶5.8、指定版本号
1 | lerna version 0.0.2 -y |
需要本地分支和远程分支无差别。
¶5.9、发布
lerna publish [--conventional-commits -y]
1 | lerna publish |
需要先执行 git commit,会打 tag,--conventional-commits
表示生成 changelog。如果包名是带 scope 的格式,如:@liuxy0551/eslint-config-liuxy0551,则需要在 package.json 中添加配置项,packages 下的每个包都需要加:
1 | "publishConfig": { |
¶六、发布整合包
lerna publish 只会发布 packages 下的包,当前文件夹并不会作为一个包发布
在 packages 文件夹下新建一个main
,作为入口:
1 | cd packages |
将 main 下 package.json 中的 name 改成如:@liuxy0551/eslint-config-liuxy0551,version 改成 0.0.0。添加依赖:
1 | lerna add --scope=@liuxy0551/eslint-config-liuxy0551 eslint@^7.0.0 |
在 packages/main 文件夹下新建 index.js,内容如下:
1 | /** Export all */ |
lerna 不会发布标记私有的项目,需要修改根目录 package.json 中的配置"private": false
1 | npm whoami |
1 | lerna publish |
访问https://www.npmjs.com/search?q=@liuxy0551/eslint-config-liuxy0551 可以看到发布的包。
常见错误
第一次发布失败后出现 Current HEAD is already released
执行lerna publish from-package
可选步骤
删除测试发布的 npm 包:
1 | npm unpublish @liuxy0551/eslint-config-liuxy0551-react --force |