使用 npm 7 工作区简化你的 monorepo
本月 npm 有发布了他们的包管理器 npm 7 的主要版本。它附带了对工作区的支持。 为什么是大新闻?因为 npm 是唯一与每个 NodeJS 捆绑在一起的包管理器。要使用 yarn 或 pnpm,您必须采取额外的步骤并首先安装它们。 继续阅读,您将了解如何在真实场景中使用 npm 7 工作区,并了解使用工作区的方式与使用 npm 的方式非常不同。 Monorepo 用例 monorepo 是
本月 npm 有发布了他们的包管理器 npm 7 的主要版本。它附带了对工作区的支持。
为什么是大新闻?因为 npm 是唯一与每个 NodeJS 捆绑在一起的包管理器。要使用 yarn 或 pnpm,您必须采取额外的步骤并首先安装它们。
继续阅读,您将了解如何在真实场景中使用 npm 7 工作区,并了解使用工作区的方式与使用 npm 的方式非常不同。
Monorepo 用例
monorepo 是一个描述包含许多项目的单个 git 存储库的术语。
设置 monorepo 的最常见原因是简化开发团队的工作,该团队维护使用共享代码的多个应用程序,例如通用用户界面库。
想象一个团队开发了两个 React 应用程序,它们共享一些常见的 UI 元素,如输入、选择器、手风琴等。最好以 React 组件的形式提取该 UI,并准备好可供所有成员使用的构建块。团队。
除此之外,在单个 IDE 实例中打开所有源文件更方便。您可以从一个项目跳到另一个项目,而无需在桌面上切换窗口。
我也只想要我的应用程序中的那个漂亮的按钮
假设我想构建两个独立的 React 应用程序,分别称为app1
和app2
,它们将使用来自一个名为ui
的通用 UI 库中的一个通用组件。我希望这两个应用程序在我编辑 UI 库中的文件时热重载。
所谓独立,我的意思是app1
对app2
一无所知,反之亦然。
以下是与 npm 7 工作区兼容的设置。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--9lQlYnqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/i/hcf8f0qc0s6gzin0fic5.png)
在 npm 7 中定义工作区
我在所有包的名称前加上@xyz以便它们与官方 npm 注册表不同。换成你的就行了。
这是整个设置中最关键的部分。在根文件夹的package.json
中插入以下内容以设置 monorepo。
{
"name": "@xyz/monorepo",
"private": true,
"version": "1.0.0",
"workspaces": [
"./common/*"
]
}
进入全屏模式 退出全屏模式
新的"workspaces"
属性让 npm 知道我想跟踪./
文件夹中的任何包,并在我运行npm install
时自动将它们符号链接到根目录的node_modules
中。
从现在开始,每当我们的 React 应用程序使用import Foo from "@xyz/ui"
时,NodeJS 都会在./node_modules/common/@xyz/ui
中找到它,它指向包含我们库的./
文件夹。完美的!工作区不再需要 /uinpm link
。
如果没有工作区,React 应用程序会抱怨它找不到名为的模块,并会开始在 npm 官方注册表中查找它。 /ui
迈出第一步
为了测试我们的设置,让我们从ui
库中共享一个文本并将该字符串导入我们的 React 应用程序。
创建通用 UI 库的package.json
:
{
"name": "@xyz/ui",
"version": "1.0.0",
"private": true,
"main": "index.js"
}
进入全屏模式 退出全屏模式
和将导出字符串的index.js
文件:
const version = "This comes from UI! 1.0.0"
export default version;
进入全屏模式 退出全屏模式
是时候将该字符串导入我们的应用程序了。
在我们的 monorepo 中快速创建 React 应用程序。只需使用新发布的 Create React App 4:
mkdir apps
cd apps
npx create-react-app app1
npx create-react-app app2
进入全屏模式 退出全屏模式
现在您会认为我们需要将ui
库添加到应用程序中。在纱线中,它如下所示:
yarn workspace app1 add @xyz/ui
进入全屏模式 退出全屏模式
但是使用 npm 我们根本不需要添加任何依赖项。
只需在 app1 和 app2 应用程序中转到您的App.js
文件,然后添加以下代码以显示我们 UI 库中的字符串:
...
import testString from "@xyz/ui";
...
<span>{testString}</span>
...
进入全屏模式 退出全屏模式
要对其进行测试,请使用以下命令:
# create a symlink to the @xyz/ui in the root folder
npm install
# go to the app's folder
cd apps/app1
# For CRA 4 you may need to add SKIP_PREFLIGHT_CHECK=true to .env file
# And use the --legacy-peer-deps flag as many packages hasn't been updated yet to officially support React 17
npm install --legacy-peer-deps
npm run start
进入全屏模式 退出全屏模式
并从另一个终端窗口:
cd apps/app2
npm install
npm run start
进入全屏模式 退出全屏模式
您将看到在您的两个 React 应用程序中呈现的This comes from UI! 1.0.0
文本!
导出 React JSX 组件
现在,如果您尝试导出 JSX 组件,React 应用程序会抱怨它们无法解析 JSX。您需要先从通用 UI 包中转译 JSX 代码。
您可以使用基本的 Webpack 5 设置:
common/ui/package.json
{
"name": "@xyz/ui",
"version": "0.2.0",
"private": true,
"module": "build/ui.bundle.min.js", # Changed main to module
"scripts": {
"build": "webpack --config webpack.prod.js",
"build-watch": "webpack --config webpack.prod.js --watch",
},
... # webpack 5 dependencies
}
进入全屏模式 退出全屏模式
.config.js
/ui/babel
module.exports = {
presets: [
[
"@babel/preset-react",
{
targets: {
node: "current",
},
},
],
],
};
进入全屏模式 退出全屏模式
.prod.js
/ui/webpack
const path = require("path");
module.exports = {
entry: {
index: { import: "./src/index.js" }
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: "babel-loader",
},
],
},
output: {
filename: "ui.bundle.min.js",
path: path.resolve(__dirname, "build"),
// Below two important lines!
library: 'xyzUI',
libraryTarget: 'umd'
},
};
进入全屏模式 退出全屏模式
我们的简单组件:
common/ui/src/index.js
import React from "react";
const UIExample = ({ text = "" }) => {
return (
<div>
<h1>Shared UI library {text}</h1>
</div>
);
};
export default UIExample;
进入全屏模式 退出全屏模式
使用以下方法在 React 应用程序中导入UIExample
组件:
apps/app1/src/App.js
...
import UIExample from "@xyz/ui";
...
<div>
<UIExample text="from app1" />
</div>
...
进入全屏模式 退出全屏模式
确保 UI 库在每次代码更改时都被转译:
cd common/ui
npm run build-watch
进入全屏模式 退出全屏模式
在单独的终端窗口中运行 app1 并注意,每当您编辑 UI 组件时,webpack 开发服务器将自动重新加载最新版本,这要归功于后台运行的 webpack watch。
cd apps/app1
npm run start
进入全屏模式 退出全屏模式
演示
下面我正在编辑常见的 UI 组件UIElement
并在保存两个 React 应用程序时会使用更新的组件自动刷新:
[](https://res.cloudinary.com/practicaldev/image/fetch/s--QkkUkGP_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/i/tbu8b7hujyin5e1h2uip.gif)
总结
借助最新的 npm 7 及其对工作空间的支持,现在可以拥有一个 monorepo,而无需任何外部工具,例如或 -workspaces
nx
。
请记住,npm 的理念与 yarn 不同。例如,您不能从 monorepo 的根文件夹中运行工作空间内的脚本。
还要认识到和 /app1
没有在 monorepo 的 package.json /app2
workspaces
属性中定义。只有将要导出的模块需要存在 ()。 /ui
npm 7 工作区主要为模块提供发现。 我希望在发行说明中强调这一点,并且 npm 的帮助示例更复杂一些。我希望这篇文章能暂时填补这个空白。
奖金
查看我的gif-css-animation-monorepo存储库,它展示了我如何使用和 HTML 页面为本文制作动画。
更多推荐
所有评论(0)