使用lerna管理大型前端项目
首页 > >    作者:lininn   2022年5月12日 11:49 星期四   热度:160°   百度已收录  
时间:2022-5-12 11:49   热度:160° 

一、前言

最近准备开发前端的一个模块化的库,业务级别,要求可以任意插拔随意组合。大型工程,需要多人维护。
以前的项目都是业务级,单个包项目。简单,便于管理。但是,当一个大的项目库代码量剧增之后,管理起来就是一件比较麻烦的事情,为了方便代码的共享,就需要将代码库拆分成独立的包。
调研了一下lerna库,适合我们的场景,babel即用这个工具进行管理。

二、lerna基础

初始化:

$ npm i -g lerna
$ mkdir lerna-repo && cd $_ $ lerna init 

生成文件路径如下:

lerna-repo/ packages/ package.json
  lerna.json 

默认情况下,packages/下即保存多包地址。

管理模式

使用lerna管理项目时,可以选择两种模式。
默认的为固定模式(Fixed mode),当使用lerna init命令初始化项目时,就默认为固定模式,也可以使用 lerna init --independent 命令初始化项目,这个时候就为独立模式(Independent mode)。
固定模式中,packages下的所有包共用一个版本号(version),会自动将所有的包绑定到一个版本号上(该版本号也就是lerna.json中的version字段),所以任意一个包发生了更新,这个共用的版本号就会发生改变。
独立模式允许每一个包有一个独立的版本号,在使用lerna publish命令时,可以为每个包单独制定具体的操作,同时可以只更新某一个包的版本号。此种模式时,lerna.json中的version字段指定为independent即可。

常用命令

  1. 启动
    lerna bootstrap
    切记使用这个指令代替 npm install。默认使用npm安装,如果需要使用yarn或者cnpm可参考4.
    这个指令会执行以下操作:
  • 在每个 package 下面执行 npm install 。
  • 根据各个 package 下 package.json 里面的 dependencies 和 devDependencies 配置,使用 symlink 在各个 package 的 node_modules 下面建立引用关系。
  • 在每个 package 下执行 npm run prepublish
  • 在每个 package 下执行 npm run prepare
  1. 添加依赖
lerna add <pkg> [globs..] /*
Add a dependency to matched packages

位置:
  pkg    Package name to add as a dependency                  [字符串] [必需]
  globs  Optional package directory globs to match             [数组] [默认值: []]
*/ 

例如目录结构为:

lerna-repo/ packages/ super-page-component/ package.json
      index.ts
      node_modules/ ... other-xxx-module/ package.json
  lerna.json 

super-page-component 添加 依赖 vue-class-component,scope后要跟package.json里面的名字,而不是文件夹名。如果全部安装,去掉scope即可。

lerna add vue-class-component --scope=@mfelibs/superpage-component 
  1. 发布
    lerna publish 用于发布更新,默认发到npm上,如需修改可参考4。运行该命令会执行如下的步骤:
  • 运行lerna updated来决定哪一个包需要被publish
  • 如果有必要,将会更新lerna.json中的version
  • 将所有更新过的的包中的package.json的version字段更新
  • 将所有更新过的包中的依赖更新
  • 为新版本创建一个git commit或tag
  • 将包publish到npm上

同时,该命令也有许多的参数,例如--skip-git 将不会创建git commit或tag,--skip-npm将不会把包publish到npm上。

  1. 指定源
    如果你的项目并不是用npm管理,像我们一样,可以在需要的操作上都指定源。
    例如使用yarn管理包 lerna bootstrap --npm-client=yarn
    例如使用cnpm发布包 lerna publish --npm-client=cnpm(注意,3.x版本无效)

三、遇到的问题

1. symlink 的问题

看我们前面提到的lerna bootstrap执行的操作第二步,使用 symlink 在各个 package 的 node_modules 下面建立引用关系。

如果我们的package中有webpack,那么其中的loader很有可能会出问题

假设 package 下面有一个包 pkg1 ,依赖 package 下面的另一个包 pkg2 。
运行 lerna bootstrap 之后, pkg1/node_modules 下就会出现 pkg2 的 symlink 。

我们遇到的问题是在pkg2中有一个TS文件,export出去。pkg1中去引入,但是发现总是没有命中真实的loader。

如果使用 webpack 系列工具来编译运行 pkg1 ,由于 webpack loader 判断路径默认是按照真实路径来的,所以 pkg2 对应到的路径是 [project root]/package/pkg2 ,而不是 [project root]/package/pkg1/node_modules/pkg2

这样一来,如果需要 pkg2 中的源码过 pkg1 的 loader (比如 pkg2 中的 TS 通过 pkg1 的 ts-loader),就需要特殊配置。这和不涉及 symlink 的真实场景存在较大差异。
同时,很多配置(比如 postcssrc 、 babelrc 、 eslintrc 等)是以 resolve 到的文件去解析的。

比如要用 babel 编译 pkg2 下面的 [project root]/package/pkg2/src/Report.ts 源码,会按照如下目录顺序查找 babelrc 配置:

[project root]/package/pkg2/src/ [project root]/package/pkg2/ [project root]/package/ [project root]/ ... 

而此时很可能希望能在 [project root]/package/pkg1/ 目录下寻找配置。

所以此时其实很希望 webpack loader 基于 symlink 的路径去解析判断 include / exclude 等配置,而不是按照真实文件的路径。

所以需要配置webpack 的 resolve.symlinks 来解决这个问题,具体参见官方文档

2. 指定cnpm源无效

gitlab issue publish时不接受参数,只能使用npm仓库。
但是旧版本 2.x 的支持,本人测试,截止到3.3.2,3.x的lerna指定cnpm源publish均无效。

二维码加载中...
本文作者:lininn      文章标题: 使用lerna管理大型前端项目
本文地址:?post=556
版权声明:若无注明,本文皆为“覆手为雨”原创,转载请保留文章出处。
分享本文至:

返回顶部    首页    手机版本    后花园   会员注册   
版权所有:覆手为雨    站长: lininn