前段时间9月21日参加了在成都举办的第五届FEDAY
, 印象比较深入的是白鹭引擎首席架构师@王泽分享的《框架开发中的基础设施搭建》,提到了在下一代白鹭引擎中使用到monorepo
模式,以用来管理多个模块,协调各个模块之间的依赖更新。vue
正好在国庆期间10月5日尤大公开了vue3.0
已完成的源码,也是采用了monorepo
管理模式,看来monorepo
确实有其独到的优点,再加上之前在项目中遇到过相关的痛点,因此深刻地了解了一下这种模式,本文将基于vue3.0
讨论如何经过monorepo
模式来管理代码的。node
monorepo
是一种将多个package
放在一个repo
中的代码管理模式,摒弃了传统的多个package
多个repo
的模式。
目前 Babel
, React
, Angular
, Ember
, Meteor
, Jest
等许多开源项目都使用该种模式来管理代码。react
repo
难以管理,编辑器须要打开多个项目;webpack
会在每一个项目中安装一次;package
代码集中在一个项目,单个项目体积较大;package
代码对全部人可见,没法作权限管理;目前业界最佳实践是采用yarn workspace
+ lerna
来实现,vue3.0
也是采用二者结合的方式来实现。webpack
yarn workspace
能够实如今一个项目中实现多个模块的依赖新增和共用,而lerna
的功能则更完善,不只能够管理多个模块,还有清除模块node_modules
,发布模块到npm,自动更新模块间版本依赖,并支持全量发布和根据改动单独发布等功能。git
yarn
官方推荐用yarn
来处理依赖安装,用lerna
来处理依赖更新和发布问题。github
下面开始基于monorepo
模式来搭建一个仿vue3.0
的项目web
$ npm i -g yarn lerna
复制代码
$ mkdir vue-next && cd vue-next
$ lerna init
// 此时项目结构
vue-next
|-packages
|-lerna.json
|-package.json
复制代码
// vue-next/package.json
"private": true, // 项目根目录下的private必须设置成true,不然workspace不会被启用
"workspaces": [ // 指定须要管理的模块
"packages/*"
],
复制代码
// 此时项目结构
vue-next
|-packages // packages下的全部包结构相似,下面仅展现了compiler-core包的目录结构
|-compiler-core // 与平台无关的编译器
|-__tests__ // 测试用例
|-src // 源文件
|-index.js // 根文件
|-package.json // 包配置
|-compiler-dom // 与浏览器相关的编译器
|-reactivity // 数据响应式系统
|-runtime-core // 与平台无关的runtime
|-runtime-dom // 与浏览器相关的runtime
|-runtime-test // 为了测试的轻量级runtime
|-server-renderer // 服务端渲染
|-shared // 内部帮助方法
|-template-explorer // 预览模版转化成render函数的工具
|-vue // 用于构建完整的vue版本
|-lerna.json
|-package.json
复制代码
项目中通常只会用到如下3种安装形式typescript
// yarn 使用 workspace 模式安装 npm 包时必须加 -W 参数
$ yarn add -W -D rollup typescript jest prettier ...
复制代码
// @vue/compiler-core 是取 vue-next/packages/compiler-core/package.json 的 name 字段
$ yarn workspace @vue/compiler-core add acorn estree-walker source-map
$ yarn workspace @vue/template-explorer add monaco-editor
复制代码
// @vue/compiler-core 是取 vue-next/packages/compiler-core/package.json 的 name 字段
$ yarn workspace @vue/compiler-dom add @vue/compiler-core@3.0.0-alpha.1 // 必定要指定正确的版本号,否则会到npm查找包
$ yarn workspace @vue/runtime-core add @vue/reactivity@3.0.0-alpha.1
$ yarn workspace @vue/runtime-dom add @vue/runtime-core@3.0.0-alpha.1
$ yarn workspace @vue/runtime-test add @vue/runtime-core@3.0.0-alpha.1
$ yarn workspace vue add @vue/compiler-dom@3.0.0-alpha.1 @vue/runtime-dom@3.0.0-alpha.1 // 可同时安装多个
复制代码
至此已经完成了项目的基础搭建(打包等工程化内容略过,本文主要介绍
monorepo
相关),彷佛主要是yarn
在工做,lerna
没有没有派上用场,下面来介绍lerna
在哪些地方能够赋能vue3.0
。npm
A tool for managing JavaScript projects with multiple packages.json
一个在js项目中用来管理多个package
的工具。
主要是便于开发者更加高效简便地管理package
自己,依赖,发布。
// 生成基本项目结构和 lerna 配置
$ lerna init
复制代码
若是须要从新安装依赖,切记在删除项目根路径的
node_modules
前进行git
提交保存,由于monorepo
模式是以软连接的形式来实现内部 package 引用的,直接删除整个node_modules
的同时会把全部package
的文件删掉,难以恢复!
建议永不进行删除整个
node_modules
的操做,能够进入node_modules
全选后再取消勾选内部package
软连接再删除。
// 给全部 package 安装依赖,在对于的目录生成 node_modules,并在 node_modules 中为内部package生成软连接
$ lerna bootstrap
// 默认会使用 npm 安装,可是本项目使用 yarn,能够指定使用 yarn
$ lerna bootstrap --npm-client=yarn // 或者在 lerna.json 配置 {"npmClient": "yarn"}
// 上述安装方式若是不一样package之间安装了同一个npm包,会形成重复安装,增长安装时间和项目体积
// 能够利用 node_modules 向上查找的特性,将全部依赖安装到项目根路径的 node_modules 中,lerna 加上 --hosit便可
$ lerna bootstrap --hosit
// 使用lerna bootstrap --npm-client=yarn --hoist
// 会有冲突,报错--hoist is not supported with --npm-client=yarn, use yarn workspaces instead
------------------------------------------------
$ yarn // 推荐!! 用 yarn workspace 特性替代 lerna bootstrap
复制代码
// 在 6.2 安装依赖时,部分npm包会给当前的package目录安装 node_modules
// 同时根路径中的 node_modules 也会安装项目
$ lerna clean
复制代码
// package.json 中设置了 "private": true 的 package 不会展现
$ lerna ls
复制代码
// package.json 中设置了 "private": true 的 package 不会展现
// 在 Independent mode 下只有改动过的 package 才会被发布
// vue3.0 采用的是 Fixed/Locked mode (default),每次都会发布全部 package,package 版本跟随项目的版本走
$ lerna changed
复制代码
// 根据当前的 lerna 模式(Fixed/Locked mode (default) 或者 Independent mode)来进行整包发布或者有改动的 package 单独发布
// 每次发布会自动更新相关package的版本号,而且会更新引用该package的其余package依赖
$ lerna publish
复制代码
本文介绍了vue3.0
中monorepo
管理模式的实现,经过yarn workspace
和lerna
二者相结合,达到了在一个repo
中高效便捷地管理多个package
的目的。
在咱们平常工做中可能没有开发白鹭引擎
,vue
这类大型框架的需求,可是这不表明咱们用不到该模式,下面我总结了几种适合monorepo
管理模式的场景:
package
单独开发,优化开发和打包时间,同时共用的组件和js方法能够做为一个package
;mint-ui
;