前段時間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
;