使用 PNPM 从零搭建 Monorepo,测试组件并发布

2024-06-14 02:20

本文主要是介绍使用 PNPM 从零搭建 Monorepo,测试组件并发布,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 目标

通过 PNPM 创建一个 monorepo(多个项目在一个代码仓库)项目,形成一个通用的仓库模板。

这里以在该 monorepo 项目中搭建 web components 类型的组件库为例,介绍从仓库搭建、组件测试到组件发布的整个流程。

这个仓库既可以用于公司存放和管理所有的项目,也可以用于将个人班余的所有积累整合其中。

2 环境要求

核心是 PNPM 和 Node.js,没有特殊的版本要求,只要他俩能对应上即可。
在这里插入图片描述

当前项目使用的 PNPM 版本为 9.3.0,Node.js 为 18.20.3。

除了以上两个,项目中也使用到了以下工具或插件,可以按需添加,如不使用则不用考虑其环境要求。
vite(v5.2.0):主要用于项目运行和构建,要求 Node.js v18+ 或者 v20+。
Storybook(v8.1.7):用于组件的测试和展示,要求 Vite v4.0 +。

3 仓库搭建

3.1 新建项目

新建一个文件夹作为项目容器。

这里起名叫 ease-life,意为轻松生活。所有的学习、工作都是为了更好地、更轻松的生活。

3.2 创建目录

3.2.1 apps

在项目根目录下创建 apps 文件夹。
在 apps 下创建 storybook 文件夹。用于测试和展示自定义的 web components。

apps 文件夹主要存放应用程序,如:Storybook、VitePress,还可以加上 vue-test、react-test 来对 web components 做测试。

3.2.2 packages

在项目根目录下创建 apps 文件夹。
在 packages 下分别创建 config(配置信息)、web-components(实现组件与框架无关) 文件夹。

  • 在 config 文件下创建 eslint、stylelint、commitlint 以及 typescript,用于存放对应的配置
  • 在 web-components 创建 text 文件夹,实现一个简单的文本组件。 text 文件夹下创建 src 文件夹。

packages 底下主要包含插件、组件、命令行、类库等,除了以上的内容还可以按需加上 vue-components、react-components、cli、map-library 等等。

形成的目录结构如下:

ease-life
|-- apps
|   |-- storybook
|-- packages|-- config|   |-- commitlint|   |-- eslint|   |-- stylelint|   |-- typescript|-- web-components|-- text|-- src

3.3 添加文件

3.3.1 PNPM 相关

  1. 在项目根目录下添加文件:pnpm-workspace.yaml,定义 PNPM 的工作空间:
packages:# 匹配 packages 目录下(任意文件夹下)的所有模块- 'packages/**'# 匹配 apps 直接子文件夹下的所有模块- 'apps/*'

这里的模块,说的是:包含 package.json,可以被发布到 NPM 远程仓库的项目。

  1. 在项目根目录下添加文件:.npmrc,定义 PNPM 的配置项:
# 允许链接工作空间中的包
link-workspace-packages = true# 在引用工作空间中的包时,设置前缀为 *,即:使用最新版本的包
save-prefix = ''

3.3.2 Vite 相关

  1. 在根目录下运行以下内容:
pnpm init

从而生成 package.json,如下:

{"name": "ease-life","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified1\" && exit 1"},"keywords": [],"author": "","license": "ISC",
}
  1. 在 web-components 以及 web-components/text 下都执行 pnpm init,或直接将根目录下的 package.json 拷贝过去。

本文的目的是要每个组件都能够被单独被发布至 NPM 仓库,如:@ease-life/text。如只需要做整个组件库的发布,则无需在 web-components/text 下执行 pnpm init。

  1. 在项目最外层空间下添加 vite:
pnpm add vite -Dw

packages 里的所有模块如无特殊情况,统一使用 vite 来运行、打包,因此只需要在项目最外层安装一次即可。

  1. 在项目根目录下,添加文件 vite.config.js:
import { defineConfig } from 'vite'export default defineConfig({build: {lib: {entry: 'index.ts',fileName: 'index'},}
})
  1. 修改之前生成的 package.json:
{"name": "ease-life","version": "1.0.0","description": "哥的幸福生活全靠你啦","scripts": {"dev": "vite --open","build": "vite build","preview": "vite preview --open"},"keywords": ["monorepo","web components","pnpm","storybook","changeset"],"author": "zqc","repository": {"type": "git","url": ""},"license": "MIT","type": "module","devDependencies": {"vite": "^5.2.0"},"engines": {"node": ">= 18.20.3","pnpm": ">= 9.3.0"}
}

3.3.3 添加 config

待完善

3.3.4 添加其他

  1. 在项目跟目录下添加 .gitignore:
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*node_modules
dist
dist-ssr
*.local# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3.3.5 自定义 Web Components

  1. 在 packages/web-components/text/src 下创建 text.ts:
import { html, css, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';@customElement('el-text')
export class ELText extends LitElement {static styles = css`p { color: blue }`;@property()name = 'Somebody';render() {return html`<p>Hello, ${this.name}!</p>`;}
}
  1. 在 packages/web-components/text 下创建 index.ts(导出当前组件):
export { ELText as default } from './src/text.ts';
  1. 在 packages/web-components/text 下添加 tsconfig.json:
{"compilerOptions": {"target": "ESNext","experimentalDecorators": true,"useDefineForClassFields": false,"module": "ESNext","lib": ["ES2020","DOM","DOM.Iterable"],"skipLibCheck": true,/* Bundler mode */"moduleResolution": "bundler","allowImportingTsExtensions": true,"resolveJsonModule": true,"isolatedModules": true,"noEmit": true,/* Linting */"strict": true,"noUnusedLocals": true,"noUnusedParameters": true,"noFallthroughCasesInSwitch": true},"include": ["src"]
}

以上内容将会被移至 packages/config/typescript 中,待修改

  1. 修改 在 packages/web-components/text 下的 package.json:
{"name": "@ease-life/text","version": "1.0.0","description": "","type": "module","files": ["dist"],"main": "./dist/index.umd.cjs","module": "./dist/index.js","exports": {".": {"import": "./dist/index.js","require": "./dist/index.umd.cjs"}},"scripts": {"build": "vite build -c ../../../vite.config.js"},"keywords": ["ELText"],"author": "","license": "ISC","dependencies": {"lit": "^3.1.2"}
}

3.4 生成 storybook

  1. 在 apps/storybook 文件夹的路径下运行以下内容:
pnpm dlx storybook@latest init

选择最后一个选项,回车。
在这里插入图片描述
此时就会在 apps/storybook 下有对应的 storybook 的内容。

  1. 删除 apps/storybook/src/stories 下自带的 button.css、Button.stories.ts、Button.ts、header.css、Header.stories.ts、Header.ts、page.css、Page.stories.ts、Page.ts 六个文件。

最终项目文件目录结构如下:

ease-life|-- .gitignore|-- .npmrc|-- package.json|-- pnpm-lock.yaml|-- pnpm-workspace.yaml|-- vite.config.js|-- apps|   |-- package.json|   |-- storybook|       |-- .gitignore|       |-- index.html|       |-- package.json|       |-- tsconfig.json|       |-- .storybook|       |   |-- main.ts|       |   |-- preview.ts|       |-- public|       |   |-- vite.svg|       |-- src|           |-- index.css|           |-- my-element.ts|           |-- vite-env.d.ts|           |-- assets|           |   |-- lit.svg|           |-- stories|               |-- Configure.mdx|               |-- Text.stories.ts|               |-- assets|                   |-- accessibility.png|                   |-- accessibility.svg|                   |-- addon-library.png|                   |-- assets.png|                   |-- avif-test-image.avif|                   |-- context.png|                   |-- discord.svg|                   |-- docs.png|                   |-- figma-plugin.png|                   |-- github.svg|                   |-- share.png|                   |-- styling.png|                   |-- testing.png|                   |-- theming.png|                   |-- tutorials.svg|                   |-- youtube.svg|-- packages|-- config|   |-- commitlint|   |-- eslint|   |-- stylelint|   |-- typescript|-- map-library|-- web-components|-- text|-- index.ts|-- package.json|-- tsconfig.json|-- src|-- text.ts

4 组件测试

  1. 在项目根目录下运行以下内容,来对 text 进行构建:
pnpm -F @ease-life/text build

会在 packages/web-components/text 下生成 dist 文件夹,里边有 index.js(ESM) 以及 index.umd.cjs(CommonJS)。

  1. 在 apps/storybook/src/stories 下添加一个 Text.stories.ts:
import type { Meta, StoryObj } from '@storybook/web-components';
import '@ease-life/text';const meta: Meta = {component: 'el-text'
};export default meta;
type Story = StoryObj;export const Default: Story = {args: {name: 'world',},
};
  1. 修改 apps/storybook 下的 package.json,将其中的 name 改为:
  "name": "@ease-life/storybook",
  1. 在项目根目录下运行以下内容来安装刚才定义的 web components:
pnpm -F @ease-life/storybook add @ease-life/text
  1. 在项目根目录下运行以下内容,来启动 storybook:
pnpm -F @ease-life/storybook storybook

在浏览器中显示以下内容,则证明组件没有问题了。
在这里插入图片描述

5 组件发布

5.1 在 NPM 官网注册

如果没有注册过,则打开 NPM,点击右上角的 Sign Up,按提示填入信息。

5.2 登录账户

注册完后直接登录。

5.3 创建组织

打开创建组织的页面,在其中添加组织名称,组织名称就是 scope 的名称,也就是这里 @ 后面的内容。

@ease-life/tex,我这里创建了 ease-life 的组织。

5.3 组件发布

  1. 用户登录,在项目根目录下运行:
pnpm login

看到提示后,再次回车,在浏览器弹出的页面中进行登录,成功后显示以下内容:
在这里插入图片描述

  1. 组件发布,在项目根目录下运行:
pnpm publish -r

会自动发布仓库中版本发生改变的组件。
在这里插入图片描述
出现以上类似内容,就证明发布成功了。

这篇关于使用 PNPM 从零搭建 Monorepo,测试组件并发布的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059102

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca