基于框架
palife-lib-fluid
的业务组件库
对于组件库有两种使用场景
palife-lib-fluid
框架的项目引用(部署在平安maven私库)palife-lib-fluid
框架的项目引用要求多包处理,即每个组件都可作为单独的依赖包进行发布,这里包括umd脚本及npm包。
├── lerna.json
├── package.json
└── packages
├── countdown
│ ├── lib
│ ├── src
│ └── package.json
├── suspendBox
│ ├── lib
│ ├── src
│ └── package.json
├── utils
│ ├── lib
│ ├── src
│ └── package.json
└── demo
├── src
├── tsconfig.json
└── package.json
lerna + yarn workspace 前者负责版本管理与发布,后者负责依赖管理
Learn 是一个通过git和npm来优化管理多包储存的工作流的工具。
lerna有两种管理模式:
固定模式
执行lerna publish时,如果代码有更新,会自动更新此版本号的值。即:所有的包公用一个版本号。版本号使用lerna.json文件中的version属性。
独立模式
允许维护人员独立的增加修改每个包的版本,每次发布,所有更改的包都会提示输入指定版本号。
lerna init --independent
或 修改lerna.json
中的version
值为independent
在这里我们使用独立模式,单独发包。
有关lerna
与npm/yarn workspace
组合方案对比推荐个比较好的文章
为什么不用lerna bootstrap
而用yarn
?
lerna bootstrap --hoist
在仓库根目录安装外部依赖,这样所有包都可以使用他们。二进制文件都将链接到依赖包的node_modules/.bin/
目录中,这样 npm 脚本就可以使用它们了。但是并不会主动软连接packages
下的包到顶层node_modules
中,这样在开发环境调试就需要主动在dependencies
中声明引用关系。
lerna bootstrap
不会提升依赖
yarn
workspace会提升依赖,并创建packages
软连接到顶层node_modules
中。确保开发环境依赖包唯一
为什么demo也要作为一个workspace
使用而不隔离?
workspaces
会执行yarn
会把各packages中的依赖包都提升到顶层,这样能保证各包运行时的依赖包指向同一个依赖。如果单单把demo项目隔离出去,它会有自己独立的node_modules
。 那么即使在dependencies
中声明了"@palife-lib-bc/suspendBox": "file:../suspendBox"
,让本地依赖包软连接到node_modules
中,但本体依然是packages
下的本地依赖包,它的引用依赖关系依然是顶层的node_modules
。由于本地组件包和demo项目的依赖包不是同一个,就会出现报错的问题,在这里就是react
报错的问题。
`react.development.js:1607 Uncaught Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app`
组件包都会有入口文件,通常是发布目录(在这里时lib)的index文件。lib文件更新通常只有发布的时候才会用tsc
编译发生,但在本地开发环境需要的是对源文件的直接引用。所以这里借助alias
对于组件包的引用重定向:
const pkgs = JSON.parse(execSync('lerna ls --json', { stdio: 'pipe' }).toString().trim())
const alias = pkgs.reduce((res, pkg) => {
pkg.shortName = pkg.name.replace('@palife-lib-bc/', '')
res[pkg.name] = `${pkg.name}/src`
return res
}, {})
module.exports = { alias, pkgs }
这样可以在开发环境实时浏览组件开发情况,方便组件开发与调试。
devDependencies、dependencies与peerDependencies的配置说明
devDependencies
开发环境依赖包。我们在开发一个 npm 包的时候,会涉及到编译和打包等等,这些操作依赖一些开发环境的包。发布出去的包在引用时该配置项会被忽略,即devDependencies
在npm包中不会被下载
dependencies
依赖包。无论本地开发环境还是发布出去的npm包,该依赖配置都会下载下来。主要是配置该npm包的依赖项。
peerDependencies
适配依赖包。由于我们在开发的时候不知道会被哪个第三方包引用,因此这种情况一般是我们根据某个会引用我们的第三方包进行的特定开发,常见的就是插件开发。在这里我们的组件包是针对palife-lib-fluid
框架开发的业务组件,所以对于这些组件来说他的适配依赖包就是palife-lib-fluid
。peerDepndencies
是不会被下载的。
该配置对于npm版本有不同表现,v6之前如果依赖包版本与该配置不符或者node_modules
不存在该配置的依赖包,npm会给出警告,提示用户自己安装。v6之后如果node_modules
不存在该配置的依赖包,npm会主动安装,如果两者版本不符,则报错安装失败。
output: {
path: path.resolve(__dir, '..', 'dist'),
filename: (pathData) => {
const { version } = pkgs.find(pkg => pkg.shortName === pathData.chunk.name)
return `[name]/${version}/index.js`;
},
library: 'PalifeBC_[name]',
libraryTarget: 'umd',
libraryExport: 'default',
}
考虑到公司cdn文件发布有固定格式要求–包名/版本号/文件
,这里要对输出文件做动态配置。
lerna publish —no-private // 忽略掉私有包,在这里为demo
lerna publish
:发布自上次发布(基于上次执行lerna publish)以来更新的包。等价于lerna version + lerna publish from-git
。
lerna publish
不会发布private
为true的包,但也是会为私有包打上标签,在这里是demo包。lerna version
会为私有包打标签。需要加过滤器--no-private