乐趣区

lerna管理package

最近发现公司一个项目的目录组织挺奇怪的,所有的子项目都放在了 packages 目录里,还有这种骚操作?特意查了下资料,发现是一种比较流行的 monorepo 项目管理模式。近几年比较火的 React,Vue,Babel 都是用的这种模式:

我们平常一般采用的都是 multiple repositories 的项目管理模式:把一个大项目拆分成若干个小项目,每个小项目都独立的放在 gitlab 上。这种模式其实也没啥不好,但是某些情况下,子项目 A 依赖子项目 B,如果子项目 B 经常改动,那么每次 B 改动了,都要修改 A,这时就非常麻烦。在开发一个前端框架或者 UI 库时,就经常会遇到上述情况,这时我们就可以考虑下monorepo

monorepo说到底也只是一个理念,那么怎么才能实现这种代码组织呢?

  • lerna
  • yarn 中的 Workspace

本文主要介绍下 lerna 的使用

源码参考

lerna

全局安装 lerna

npm i lerna -g

lerna 是基于 git 的,在 github 上新建一个项目learn-lerna

git clone git@github.com:deepred5/learn-lerna.git
cd learn-lerna

初始化项目:

lerna init

lerna 会自动创建一个 packages 目录夹,我们以后的项目都新建在这里面。同时还会在根目录新建一个 lerna.json 配置文件

{
  "packages": ["packages/*"],
  "version": "0.0.0" // 共用的版本,由 lerna 管理
}

创建 package

我们创建两个 package:

cd packages
mkdir prpr-lerna-core
cd prpr-lerna-core
npm init -y
cd packages
mkdir prpr-lerna-popular
cd prpr-lerna-popular
npm init -y

注意:这两个 package 我们最后都是要发布到 npm 上的,所以名字请取特殊些,不能被人用过

添加依赖

prpr-lerna-popular依赖prpr-lerna-core,这时有两种方法添加依赖:

第一种方法是修改prpr-lerna-popular/package.json,添加

{
  "dependencies": {"prpr-lerna-core": "^1.0.0"}
}

然后运行lerna bootstrap

第二种方法是直接使用命令add

lerna add prpr-lerna-core --scope=prpr-lerna-popular

运行之后,我们发现 prpr-lerna-popular 生成了 node_modules,而node_modules 里生成了指向 prpr-lerna-core软链 ,类似npm link 的效果:

新建prpr-lerna-core/index.js

const API = 'https://yande.re/post/popular_recent.json';

module.exports = {API}

prpr-lerna-popular除了依赖prpr-lerna-core,还可以依赖其他开源的库,比如我们使用axios

lerna add axios --scope=prpr-lerna-popular

新建prpr-lerna-popular/index.js

const {API} = require('prpr-lerna-core');
const axios = require('axios');

const getPopularImg = () => axios.get(API)

module.exports = getPopularImg;

// 测试代码,发布时删除
getPopularImg().then((res) => console.log(res.data.length));

测试一下:
node packages/prpr-lerna-popular/index.js
正常情况下可以输出结果

发布到 npm

首先把所有的代码提交

cd learn-lerna
git add .
git commit -m "test publish"

注册一个 npmjs 账户

npm login

登入你的账户,如果本地 npm 是淘宝镜像,一定要换回 https://registry.npmjs.org/ 地址!!!

lerna publish

运行publish,选择发布的版本号

lerna 可以帮我们管理版本号,非常方便!

常用命令

lerna init #初始化
lerna bootstrap #下载依赖包或者生成本地软连接
lerna add axios #所有包都添加 axios
lerna add prpr-lerna-core --scope=prpr-lerna-popular #给包 prpr-lerna-popularx 添加 prpr-lerna-core 依赖
lerna list
lerna clean

其他事项

  • lerna 默认使用的是集中版本,所有的 package 共用一个 version。如果希望不同的 package 拥有自己的版本,可以使用 Independent 模式
  • 发布 package 的名字如果是以 @ 开头的,例如 @deepred/core,npm 默认以为是私人发布,需要使用npm publish --access public 发布。但是 lerna publish 不支持该参数,解决方法参考: issues

参考

浅谈 monorepo

退出移动版