将 React Components 包添加到 Monorepo
在这篇文章中,我将向现有的 monorepo(以及 Storybook)添加一个 React 组件包,并使用 GitHub 操作自动将其发布到 NPM,最后会带来一个令人不安的惊喜 ;) monorepo 是我的“Pedalboard” monorepo,在这篇文章
中有更详细的描述。
我选择添加的组件是我破旧的、真的没什么可写的,分页组件,但是嘿 - 仍然是一个 React 组件 :) 让我们开始吧 -
我将手动执行此操作,但我建议如果您的 monorepo 应该由许多开发人员使用并包含许多组件,那么您应该为其提供一种包生成器,以便创建的包保持一致并且开发体验良好。
我首先在“packages”目录下添加一个“components”目录,并在其中添加一个“src”目录。
然后,我将 cd 到该目录并初始化 yarn,如下所示:
cd packages/components && yarn init
创建初始 package.json 文件后,我会将其名称更改为包含@pedalboard
命名空间,添加 Jest 和 Eslint 作为开发依赖项,并将其发布配置标记为“public”(这样它就不会继承根项目的“private”配置)。我的 package.json 现在如下所示:
{
"name": "@pedalboard/components",
"version": "0.0.0",
"description": "A set of well-crafted components",
"main": "index.js",
"author": "Matti Bar-Zeev",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"scripts": {
"test": "echo \"Still no test specified\" && exit 0",
"lint": "eslint ./src"
},
"devDependencies": {
"eslint": "^8.4.1",
"jest": "^27.4.3"
}
}
(我们仍然没有运行任何测试,所以 yarn 测试脚本没有任何作用)
我还将在包的根目录中创建一个“index.js”文件,它将作为该包未来所有组件的导出桶。
如上所述,该组件是 Pagination 组件,它是一个简单的分页组件(您可以在之前的文章中阅读更多详细信息,我在其中将其从 render-props 迁移到了 Hooks)。
它是一个 React 组件,因此我们首先获取 React 和 ReactDOM 包作为依赖项,但这些是同级依赖,因为我们假设任何要使用此组件包的人都会从已经包含这些包的项目中执行此操作。
Yarn add react react-dom -P
现在,我将组件的源代码添加到 Pagination 目录(您可以查看GitHub 仓库中的源代码),虽然我们已经有了组件的完整逻辑,但我们仍然无法将其渲染到屏幕上。为此,我希望将 Storybook 用于我的组件——让我们开始吧:
按照Storybook 的文档,我将在组件包上初始化它 -
npx sb init
没错……所有 Storybook 依赖项都被提升到了根项目的 node_modules 目录下(我们之前用的是 Yarn Workspaces,还记得吗?),并且在 components 包的 src 目录下新建了一个名为 “stories” 的目录。
此外,init 进程还在我的 package.json 文件中添加了两个新的 npm 脚本:
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
Storybook 的新版本似乎在将 react 和 react-dom 作为同级依赖项时出现了问题。我目前找到的建议是,要么将这些依赖项放在 package.json 的依赖项部分,要么降级 Storybook 的版本。不得不承认,这两种方法都很糟糕。我尝试了一些方法,似乎有效——在组件包中,react 和 react-dom 仍然是同级依赖项,但在 monorepo 的根项目中,我已将它们作为依赖项。是的,我认为这是一个比较好的解决方案……
我想现在是时候看看是否有效果了,对吧?
Yarn storybook
没错!我们已经启动并运行了一些现成的故事。
现在是时候为分页组件编写我自己的故事了,以确保一切按预期工作:
import React from 'react';
import Pagination from '../Pagination';
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
title: 'Example/Pagination',
component: Pagination,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
onPageChange:{ action: 'Page changed' },
},
};
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template = (args) => <div><Pagination {...args} /></div>;
export const Simple = Template.bind({});
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Simple.args = {
pagesCount:10,
cursor:3,
pagesBuffer:5,
};
这是我的组件:
虽然有些功能问题不太明显,但这是一个好的开始:)我的 monorepo 上有一个组件,它包含在我的组件目录(又名 Storybook)中。
在提交这些更改之前,让我们先设置一下这个包的 ESlint 配置,使其适应 React 的特性。我会将eslint-plugin-react
插件添加到包的 dev 依赖项中。
yarn add eslint-plugin-react -D
我的 .eslintrc.json 如下所示:
{
"env": {
"browser": true,
"commonjs": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {}
}
(sourceType 作为模块支持 ESM 导入/导出和 ecmaFeatures,包括用于 React 的“jsx”)
那么,如果我把这个组件包推送到我的 GitHub 仓库,它会作为 Monorepo 的 GitHub 操作的一部分发布吗?我们来验证一下:
我添加了所有更改并给出了我的提交消息:
feat: Add the first component to the components package
GutHub 操作启动了管道,并且确实将其发布到 NPM:
好的 :)
等等……我注意到,虽然我没有修改 monorepo 上的另一个包(eslint-plugin-craftsmanslint),但它的版本仍然升级并发布到了 NPM。这真是令人不安。为什么会发生这种情况?
从这个帖子中我了解到,这可能是因为 GitHub 在签出代码时没有同时获取完整的标签历史记录,因此 Lerna 很难确定到底发生了什么变化。所以我在 npm-publish.yml 的签出命令中添加了这条指令。
- uses: actions/checkout@v2
with:
fetch-depth: 0
现在我们尝试发布一些对 components 包的修复,看看是否只有 components 包会更新并发布。我添加了一个空测试,然后推送了它……
是的!只发布了组件包。
好了,现在我们有了:
Pedalboard monorepo 下一个新的组件包,里面只有一个组件(我承认它很丑)。我们还有一个很酷的 Storybook 目录,可以展示这个组件以及任何未来会用到的组件。Eslint 可以正常工作,甚至还有一个空的测试 ;) 我们确保只有修改过的包才会发布到 npm,方法是在 GitHub 上签出代码时获取所有标签历史记录……我想,就是这样了。
当然,所有最近的代码都位于Pedalboard monorepo中,因此您可以在那里检查最近的代码更改,并且如果您对如何改进它或任何其他技术有任何想法,请务必与我们分享!
嘿!如果你喜欢刚才读到的内容,可以在推特上关注@mattibarzeev 🍻
鏂囩珷鏉ユ簮锛�https://dev.to/mbarzeev/adding-a-react-components-package-to-a-monorepo-3ol5