搭建Vue3组件库:第十二章 使用 Monorepo 方式管理组件生态

简介: 本章介绍采用Monorepo的方式管理组件生态

组件库一般都会配有周边产品,比如 AdminTemplateCLI 工具等等。周边产品相当于有关联的多个项目,更准确的说法是多个软件包。这个时候就应该使用 Monorepo 方式组织代码,方便频繁在多个项目间同时交替开发,同时发布,保持版本间没有冲突。

  • 传统 Mutirepo 方式的不足

所谓传统方式,我们称之为 Multirepo 方式,或者可以称之为 MutiPackage-MultiRepo 方式。就是说遇到多个软件包的场景,使用多个 Repo 仓库的方式组织代码。

换句话说就是,一个软件包一个 Repo 仓库。其实我们常见的前端项目默认就是这样的模式。这种方式最大的问题就是在多个项目间切换开发会非常不方便。比如: 在开发 Admin 项目的时候,发现 UI 库需要增加了一个功能,那你需要以下步骤:

  • Git 库克隆 UI 库代码;
  • 修改 UI 库代码;
  • 推送 UI 库到 Git 库;
  • 推送 UI 库到 NPM 库;
  • Admin 中更新最新的 UI 库。

这个过程假设一次修改不满意频繁更新,那么整个过程还会不断重复。

优化的方案,是使用 npm link 方式把几个项目的本地目录链接起来。但是这种方法依然有弊端,比如在团队开发的时候,你必须随时同步所有的代码仓库。另外如果你的代码不希望公开到 NPM 上,你还需要建立私有的 NPM 仓库。

  • Monorepo 的优势

Monorepo 其实就是将多个项目 (pacakage 软件包)放到同一个仓库 (Repo) 中进行管理。这种代码组织形式可以更好地管理多 Package 项目。主要的优点有:

  • 可见性 (Visibility): 每个开发者都可以方便地查看多个包的代码,方便修改跨 Package 的 Bug。比如开发 Admin 的时候发现UI 有问题,随手就可以修改。
  • 更简单的包管理方式(Simpler dependency management): 由于共享依赖简单,因此所有模块都托管在同一个存储库中,因此都不需要私有包管理器。
  • 唯一依赖源(Single source of truth): 每个依赖只有一个版本,可以防止版本冲突,没有依赖地狱。
  • 原子提交: 方便大规模重构,开发者可以一次提交多个包(package)。

同样是上面的那个同时开发 AdminUI 的场景。当你开发 Admin 时,发现UI 有要修改之处,只需要切换目录修改,这时候马上就可以验证修改后的效果了,无需提交软件包,无需担心软件冲突。

越复杂的场景,你会发现这种好处会更加明显。比如一个 UI 库对应两个Admin 。这时候你希望重构一下某个组件的属性。这种重构需要同时调整三个包中的代码。使用 Monorepo ,你可以不必有任何心智负担,调整后立刻验证两个 Admin 效果,同时发布就好。


方案选型

目前 JS 中常见的 Monorepo 大概有两种选择:LernaPnpm workspace

其实在 Pnpm 横空出世前,基本上就是 lerna 一统天下的局面。连 Vue3 早期都是使用 lerna 做的 Monorepo 方案。

lernaJS 是由 Babel 团队编写的多包管理工具。因为 Babel 体系的规模庞大后有很多子包需要管理,放在多个仓库管理起来比较困难。

babel/packages 地址

在这里插入图片描述

以上图片只是一小部分,但是也已经很多了。

2021 年底 Pnpm 横空出世,闪电般的性能一下子征服了所有前端开发者。更重要的是它还附带 monorepo 方案。这个时候基本上没有任何开发者会抵挡这种诱惑,包括Vue3.0

最终毫无疑问,我们选择 Pnpm 来搭建我们的技术方案。


修改软件包目录结构

├── packages
|   ├── smarty-ui-vite  // UI组件库
|   |   ├── package.json
|   ├── docs-vite // docs文档
|   |   ├── package.json
├── package.json

首先将原有的组件库代码移动至 smarty-ui-vite目录。

在这里插入图片描述


初始化Monorepo软件包

  • 在根目录重新初始化一个 npm。
pnpm init

然后需要在软件包中禁用 npmyarn。这一步的目的是允许项目使用 pnpm 进行模块管理。不然的话会出现不兼容问题。

方法是添加 preinstall npm hook 钩子,这个钩子会在安装模块前触发,检查该代码是否是使用 pnpm 运行。如果不是的话会推出并提示错误。

文件名:./scripts/preinstall.js

if (!/pnpm/.test(process.env.npm_execpath || '')) {
    console.warn(
      `\u001b[33mThis repository requires using pnpm as the package manager ` +
        ` for scripts to work properly.\u001b[39m\n`
    )
    process.exit(1)
  }

文件名:package.json

"scripts": {
  "preinstall": "node ./scripts/preinstall.js"
}

或者可以考虑使用

"scripts": {
    "preinstall": "npx only-allow pnpm"
}

初始化工作空间

monorepo项目中,每个软件包会存放在工作空间,方便管理。

首先需要创建一个 pnpm-workspace.yaml,这个文件用于声明所有软件包全部存放在 packages 目录之中。其实目前 monorepo 风格的项目也普遍使用 packages 作为默认软件包目录位置。

文件名:pnpm-workspace.yaml

packages:
  # all packages in subdirs of packages/ and components/
  - 'packages/**'

创建一个新的软件包

由于 smarty-ui-vite 这个组件库包已经放在 packages 目录之中了。无需其他过多的设置,它就可以当做 monorepo 工程中的一个项目了。

下面我们试试从零开始如何使用 pnpm 创建一个子软件包,并正确引用组件库。

比如:创建一个 docs-vite 用于文档化建设。在做文档化时需要引用 smarty-ui-vite 这个库,用于在网页上直接展示组件运行效果。

  • 初始化项目

创建packages/docs-vite目录

cd .\packages\docs-vite
pnpm init
  • 安装 Vite

这个时候就可以做一个选择了,假设我们认为 Vite 多个软件包都需要依赖,这个时候就可以选择将依赖安装到 workspace 中,这样每个包都可以使用 vite 而无需单独安装。

# 安装 workspace 中
pnpm i vite -w

如果只安装在子 package 里面,可以使用 -r ,比如:

# 子package安装
pnpm i vue -r --filter smarty-ui-vite

# 或者 直接在 docs-vite 目录下
pnpm i vue

下面需要做的是将 study-vue-ui 安装到 docs-vite 中。

# 内部依赖package安装
pnpm i  study-vue-ui -r --filter docs-vite

注意:study-vue-ui 是指你package.josnname,并不是文件夹名称

在安装后, docs-vitestudy-vue-ui 的位置会指向到 workspace ,这也是 monorepo 的精髓所在。

{
  "name": "docs-vite",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vite"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "study-vue-ui": "workspace:^1.0.4",
    "vue": "3.2.37"
  }
}

编辑一个页面测试一下, 直接加载 node_module 中的 smarty-ui-vitemodulecss

文件名:packages/docs-vite/index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <h1>🔨 SmartyUI Demo</h1>
    <div id="app"></div>
    <script type="module">
        import style from "study-vue-ui/dist/assets/entry.cb9ba4f4.css"
        import { createApp } from "vue/dist/vue.esm-bundler.js";
        import SmartyUI,{SFCButton,JSXButton,MyButton} from "study-vue-ui/dist/smarty-ui.mjs";

        createApp({
            template: `
        <div style="margin-bottom:20px;">
            <SButton color="blue">主要按钮</SButton>
            <SButton color="green">绿色按钮</SButton>
            <SButton color="gray">灰色按钮</SButton>
            <SButton color="yellow">黄色按钮</SButton>
            <SButton color="red">红色按钮</SButton>
        </div>
        
        <div style="margin-bottom:20px;">
            <SButton color="blue"  icon="search">搜索按钮</SButton>
            <SButton color="green"  icon="edit">编辑按钮</SButton>
            <SButton color="gray"  icon="check">成功按钮</SButton>
            <SButton color="yellow"  icon="message">提示按钮</SButton>
            <SButton color="red" icon="delete">删除按钮</SButton>
        </div>
        <div style="margin-bottom:20px;">
            <SButton color="blue"  icon="search"></SButton>
            <SButton color="green"  icon="edit"></SButton>
            <SButton color="gray"  icon="check"></SButton>
            <SButton color="yellow"  icon="message"></SButton>
            <SButton color="red"  icon="delete"></SButton>
        </div>
    `}).use(SmartyUI).mount('#app')

    </script>
</body>

</html>
  • 添加启动命令并运行
"scripts": {
    "dev": "vite"
  },
pnpm dev
  • 浏览器查看结果

在这里插入图片描述

相关文章
|
2月前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
146 64
|
12天前
|
JavaScript API 数据处理
vue3使用pinia中的actions,需要调用接口的话
通过上述步骤,您可以在Vue 3中使用Pinia和actions来管理状态并调用API接口。Pinia的简洁设计使得状态管理和异步操作更加直观和易于维护。无论是安装配置、创建Store还是在组件中使用Store,都能轻松实现高效的状态管理和数据处理。
44 3
|
2月前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
41 8
|
2月前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
34 1
|
2月前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
44 1
|
6天前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
48 1
|
16天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
2月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
48 1
vue学习第一章
|
2月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
34 1
|
2月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
40 1
vue学习第四章

热门文章

最新文章