Monorepo风格的组件工程搭建示例详解

目录
  • Monorepo概念
    • Monorepo的优缺点
  • 项目工程的搭建
    • 技术选型
    • 项目的大概结构
  • 项目配置
    • Monerepo工程的起步
    • lint、prettier、eslint的接入
    • 统一开发环境
    • packages子包搭建
    • ui-h5搭建
    • ui-taro搭建
    • icon搭建
    • hooks搭建
    • examples浏览器端演示包搭建
    • 项目的构建与npm包发布
    • 关于单元测试
  • 最后

Monorepo概念

随着各种技术的发展和超级应用的出现,人们开始考虑怎么才能将所有的小应用都集成在一个大项目中,特别是在这些项目互相影响时,在实现过程中,工程师们最关注的两点是:项目功能分离 和 避免重复代码

如果将每个功能作为独立的项目打包,随着业务的发展,项目会越来越多,根本没法管理,项目与项目之间的协作也会越来越困难,所以Monorepo的概念并产生了。

Monorepo中我们可以在一个项目下进行功能拆分,他们互相独立不影响,但是又可以通过引用来达到互相协助。

Monorepo的优缺点

优点:

  • 简化依赖的管理。
  • 跨组合作更加方便。
  • 代码复用简单。

缺点:

  • 项目构建时间过长。
  • 版本信息杂糅不清晰。

我也会基于Monorepo的方式搭建属于自己的组件库工程。

项目工程的搭建

技术选型

  • 基于pnpmMonorepo工程,项目打包工具vitegulp,使用sass处理样式。
  • Vue组件写法会支持Jsxtemplate的方式。项目支持Typescript
  • lint规范的接入,prettier的格式化统一,husky的卡点校验。
  • 组件单元测试使用vitest+happy-dom

基于以上的技术开始搭建我们的项目。

项目的大概结构

// vb-design
|—— config        //放置一些脚本
|—— examples      //存放演示包
    |—— demo
    |—— taro-demo
    ...
|—— packages      //存放npm库的包
    |—— hooks
    |—— icon
    |—— ui-h5
    |—— ui-taro
    ...
.eslintignore
.eslintrc.js
.gitignore
.lintstagedrc.cjs
.npmrc
.prettierrc.cjs
package.json
pnpm-workspace.yaml
README.md
tsconfig.root.json
...

项目配置

Monerepo工程的起步

pnpm搭建Monorepo是非常简单的,只需要我们配置pnpm-workspace.yaml文件即可。具体的配置可参考pnpm-workspace.yaml | pnpm

lint、prettier、eslint的接入

lintprettiereslint的配置大部人应该都很熟练了,在这我就不一一贴代码说明了。还不清楚的小伙伴可参考我的代码或者找篇相关的教程自己跟着试试。

统一开发环境

开发环境的统一,主要是统一Node版本和pnpm,我们可以通过在package.json中配置一些字段来统一开发环境。

1、限制Node版本和pnpm通过配置voltaengines限制Nodepnpm的版本

//package.json
"volta": {
    "node": "16.13.0"
},
"engines": {
    "node": "16.13.0",
    "pnpm": ">=6"
}

2、限制项目只能通过pnpm初始化依赖

//package.json
"scripts": {
    "preinstall": "npx only-allow pnpm",
}

packages子包搭建

对于子包的搭建,不会详细地一一讲解,需要深入了解的可以自行到源代码里看。

ui-h5搭建

  • 目录结构设计
//ui-h5
components                  //组件目录
    |—— Button
        |—— demo            //demo演示存放目录
            |—— base.vue
            ...
        |—— index.md        //组件使用文档
        |—— index.scss      //组件样式
        |—— index.ts        //vue组件
        |—— index.taro.ts   //taro组件
    |—— Icon
    ...
style          //公共样式存放
    |—— index.scss
    ...
ui.h5.ts       //vue组件对外暴露
ui.taro.ts     //taro组件对外暴露

为了开发方便,把vue端taro端的组件都放在该包下,以及examples需要的演示文档和demo也放在该包下。至于各端写好的组件demo演示文档是怎么使用,后续会说明。

  • 构建产物
// dist
components                    //单个组件
    |—— Button
        |—— index.scss
        |—— index.css
        |—— index.js
        |—— index.taro.js
    |—— Icon
    ...
style
    |—— index.scss
    ...
types
    |——
    ...
style.css
vb-ui.es.js
vu-ui.umd.js
vb-ui.taro.es.js
vb-ui.taro.umd.js

ui-taro搭建

该包其实没有做更多的事情,只是初始化之后把package.json做了相关配置。最重要的地方是在根目录下的package.json配置了脚本,在ui-h5包构建之后,通过脚本copy了该包需要的东西。

  • 脚本文件都在根目录config

icon搭建

ui-h5中,Icon组件的设计支持了iconfontsvg的方式,这也是参考了element-uiIcon组件设计。所以该包主要是处理svg图标,把图标转化成vue组件统一向外暴露的过程。

另外,我并不会用设计软件,没有svg可用,所以借用了字节arco-design的图标Arco Design Icons – Figma

hooks搭建

该包主要是一些公共方法的包,目前也没有更多的想法,所以也只是先放着。

examples浏览器端演示包搭建

因为搭建的是移动端组件库,所以演示包需要有两个入口,H5端和PC端。整个搭建的过程大致是:

vite-plugin-pagesvite-plugin-vue-layouts的配置

//vite.config.js
Pages({
  dirs: [
    {
      dir: resolve(__dirname, '../../packages/ui-h5/components'),
      baseRoute: 'component',
    },
  ],
  exclude: ['**/components/*.vue'],
  extensions: ['vue', 'md'],
}),
Layout({
  layoutsDirs: 'src/layouts',
  defaultLayout: 'preview',
})

项目的构建与npm包发布

这么多的子包,打包构建以及推送到npm是不是需要到每个子包下执行完打包和执推送的命令?针对这个问题pnpm官方是有解决方案的:

首先所有的子包都定义个build命令来执行当前包的所有打包构建事情,最后项目根目录package.json的配置如下:

//package.json
"scripts": {
    "build": "pnpm --filter './packages/**' run build && pnpm run build:taro",  //执行packages下所有子包的build方法
    "release": "pnpm run build && pnpm run release:only",
    "release:only": "changeset publish --tag=beta --access=publish",            //发布所有子包
    "build:taro": "node ./config/build-taro.js",
    "build:demo": "pnpm --filter './examples/**' run build"
}

上方build这个地方的配置pnpm官方有很详细的说明。再就是关于npm publish的,主要是通过@changesets/cli这个cli工具去解决。

changeset publish 只是一个很纯净的发包命令,手动提升/修改版本后再 changeset publish他会将所有包都publish一次。

  • 写到这,顺便再给大家说下这个项目的代码发布流吧。
  • 版本号是手动修改的。
  • 通过打tag的方式会触发workflows去执行打包构建,然后publish和部署演示的demo

很多开源的项目通过changeset-bot + changesets/action + @changesets/cli能玩出各种各样的工作流。

关于单元测试

单测在开源项目里是不可缺少的存在,虽然我不一定会去写单测

(0)

相关推荐

  • Vue3 企业级组件库框架搭建 pnpm monorepo实战示例

    目录 引言 1 组件库工程应该具备的功能 2 环境准备 3 搭建 monorepo 项目 3.1 创建项目 3.2 配置 workspace 引言 基于 vite3 vue3 的组件库基础工程 vue3-component-library-archetype 和用于快速创建该工程的工具 yyg-cli,但在中大型的企业级项目中,通常会自主搭建这些脚手架或加速器.优雅哥希望每位前端伙伴能知其所以然,故接下来的文章将进入 Vue3 企业级优雅实战 系列,整个系列将包括五大部分: 首先会分享如何从 0

  • Vue3中使用pnpm搭建monorepo开发环境

    目录 前言 Pnpm 和 Monorepo 搭建开发环境 创建项目 配置 monorepo 安装依赖 初始化Typescript 准备两个模块 shared reactivity 编写构建脚本 完成第一次调试 小结 前言 Vue3 源码阅读系列,计划从环境搭建开始,将 Vue3 的响应式模块,运行时模块和编译器模块,以及状态库 Pinia.路由库 Vue-Router的核心原理做一个梳理.这大概是一个漫长的过程.祝自己不要烂尾,祝大家有所收获. Pnpm 和 Monorepo Pnpm 是新一代

  • vite前端构建Turborepo高性能monorepo方案

    目录 引言 什么是monorepo ? 引言 之前的一篇文章我选择了go做前端的cli工具链,现在出现了新的项目构建神器Turborepo用于Monorepo 方案. 什么是monorepo ? Monorepo是一种项目管理方式,在Monorepo之前,代码仓库管理方式是 MultiRepo,即每个项目都对应着一个单独的代码仓库每个项目进行分散管理 这就会导致许多弊端,例如可能每个项目的基建以及工具库都是差不多的,基础代码的重复复用问题等等... TurboRepo 是构建Javascript

  • 前端工程Monorepo项目管理方式

    目录 什么是 Monorepo? MultiRepo 之痛 1.代码复用 2.版本管理 3.项目基建 Monorepo 的收益 Monorepo 的落地 总结 随着前端工程日益复杂,某些业务或者工具库通常涉及到很多个仓库,那么时间一长,多个仓库开发弊端日益显露,由此出现了一种新的项目管理方式——Monorepo.本文主要以 Monorepo 的概念.MultiRepo的弊端.Monorepo 的收益以及Monorepo 的落地这几个角度来认识和学习一下 Monorepo,文末会有思考题,欢迎大家

  • Monorepo风格的组件工程搭建示例详解

    目录 Monorepo概念 Monorepo的优缺点 项目工程的搭建 技术选型 项目的大概结构 项目配置 Monerepo工程的起步 lint.prettier.eslint的接入 统一开发环境 packages子包搭建 ui-h5搭建 ui-taro搭建 icon搭建 hooks搭建 examples浏览器端演示包搭建 项目的构建与npm包发布 关于单元测试 最后 Monorepo概念 随着各种技术的发展和超级应用的出现,人们开始考虑怎么才能将所有的小应用都集成在一个大项目中,特别是在这些项目

  • svgicon组件使用方法示例详解

    目录 场景 编写SvgIcon组件 组件文件结构 icons文件结构 vue.config.js配置 最终效果 场景 最近在研发产品的过程中,ued切了很多svg的图片:咱们在使用过程中除了背景图再就是使用<img :src="url"/>进行使用. 在你进行公共组件编写的时候,使用图片路径这种方式编写完组件发布之后:在再项目中引入已发布的组件,在你运行代码的时候图片路径会附带上当前运行的域名,导致图片显示不出来. 那么怎么解决这种问题呢? 和UED进行沟通让他们把这种sv

  • 微前端之Web组件自定义元素示例详解

    目录 我们知道的 Web组件使用 名称规范 组件传参数并可以写模板包括js和css Shadow Dom 影子节点 类中的构造函数和钩子函数 getter/setter属性和属性反射 扩展原生 HTML 我们知道的 第一:我们熟知的HTML标签有 a, p, div, section, ul, li, h2, article, head, body, strong, video, audio 等等 第二:我们知道,a标签是链接,p标签是段落,div是块级,h2是字体,strong 是粗体,vid

  • React元素与组件的区别示例详解

    目录 从问题出发 元素与组件 元素 组件 问题如何解决 自定义内容 第一种实现方式 第二种实现方式 第三种实现方式 从问题出发 我被问过这样一个问题: 想要实现一个 useTitle 方法,具体使用示例如下: function Header() { const [Title, changeTitle] = useTitle(); return ( <div onClick={() => changeTitle('new title')}> <Title /> </div

  • 比ant更丰富Modal组件功能实现示例详解

    目录 有哪些比ant更丰富的功能 render部分 渲染黑色蒙层 渲染弹框主体 设置body overflow:hiiden 有哪些比ant更丰富的功能 普通的modal组件如下: 我们写的modal额外支持,后面没有蒙版,并且Modal框能够拖拽 还支持渲染在文档流里,上面的都是fixed布局,我们这个正常渲染到文档下面: render部分 <RenderDialog {...restState} visible={visible} prefixCls={prefixCls} header={

  • Flutter SizedBox布局组件Widget使用示例详解

    目录 正文 child 的 constrains 确定自己的大小 SizedBox 的命名构造函数们 SizedBox.expand SizedBox.shrink SizedBox.fromSize SizedBox.square 应用场景 为 child 提供 tight 约束. 为 children 之间提供空白. 占位 正文 Flutter Sizedbox 是一个 布局组件,用来给 child 添加 tight 约束的,也可以用来添加空白. width,height是 Sizedbox

  • React实现数字滚动组件numbers-scroll的示例详解

    目录 一.设计原理 二.实现方式 三.使用方式 四.参数说明 数字滚动组件,也可以叫数字轮播组件,这个名字一听就是非常普通常见的组件,第一反应就是想找找网上大佬的东西顶礼膜拜一下,这一搜,还真是没找到趁手的╮(╯▽╰)╭. 最近接了大屏的需求,数字滚动肯定是免不了的,所以开始撸袖子,造轮子了( numbers-scroll ). 首先给大家看下轮子的效果吧: 一.设计原理 如果要做到数字滚动效果,就一定要让数字有从下往上移动的感觉.如果只是纯粹的数字变化,显示出来的效果就会比较普通了,没有什么视

  • idea聚合工程搭建过程详解

    目录 前言 一.创建父工程 1.New Project 2.聚合父工程的名字 3.指定maven仓库 4.字符编码 5.注解生效激活 6.java编译版本选8 7.File Type过滤 8.父工程POM 二.Maven工程细节复习 三.创建子工程 1.微服务提供者支付Module模块 2.微服务消费者订单Module模块 3.创建common共用 注:本篇文章主要参考周阳老师讲解的cloud进行整理的! 前言 本章主要以order订单服务来远程调用payment支付服务为例,当然这里只是简单的

  • Flutter 首页必用组件NestedScrollView的示例详解

    昨天Flutter 1.17版本重磅发布,新的版本主要是优化性能.修复bug,有人觉得此版本毫无亮点,但也从另一方面体现了Flutter目前针对移动端已经较为完善,想了解具体内容,文末有链接,如果你想升级到最新版本,建议慎重,有些人升级后项目无法运行. 今天介绍的组件是NestedScrollView,大部分的App首页都会用到这个组件. 可以在其内部嵌套其他滚动视图的滚动视图,其滚动位置是固有链接的. 在普通的ScrollView中, 如果有一个Sliver组件容纳了一个TabBarView,

  • vue弹窗父子组件调用问题示例详解

    目录 一.vue弹窗 父子组件 emit 传图片 二.vue父组件调用子组件里的不同方法 一.vue弹窗 父子组件 emit 传图片 1.:modal-append-to-body="false"为了解决element ui中引入dialog窗口组件后遮罩层会挡住dialog窗口的用处,默认为true,改为false即可解决. 2.此弹窗主要为了解决收到下位机急停信号后,上位机前台显示弹窗的重复性. //此为子组件(customComponents.vue) <div> &

随机推荐