2025年`monorepo` 中 `hoist` 机制导致加载配置文件路径的变化

`monorepo` 中 `hoist` 机制导致加载配置文件路径的变化monorepo 中 hoist 机制导致加载配置文件路径的变化 前言 作为一名前端 我们经常会在项目里添加大量的配置文件 用来配置各种各样的库和开发工具 比如配置 typescript 我们会添加 tsconfig json 配置 npm yarn pnpm 这种包管理工具 我们会添加 npmrc

大家好,我是讯享网,很高兴认识大家。

Image
讯享网

monorepohoist 机制导致加载配置文件路径的变化

前言

作为一名前端,我们经常会在项目里添加大量的配置文件,用来配置各种各样的库和开发工具。

  • 比如配置 typescript,我们会添加 tsconfig.json
  • 配置 npm,yarn,pnpm 这种包管理工具,我们会添加 .npmrc
  • 配置 eslint,我们要配置 .eslintrc.js.eslintignore
  • 配置格式化,要配置 .editorconfig.prettierrc…。
  • 配置 git.gitignore.gitattributes
  • 配置 jestjest.config.ts
  • babel -> babel.config.js
  • postcss -> postcss.config.js
  • webpack -> webpack.config.js
  • .env,.env.dev,.env.sit,.env.prod,.env.local
  • vite.config.[jt]s,vue.config.js,lerna.json,rollup.config.[jt]s,stylelint.config.js,tailwind.config.js,.browserslistrc,serverless.yml,Dockerfile,nginx.conf

看到这么多配置文件,只能说前端好累,工作好苦,学不动躺平了。

配置文件的作用域

在通常情况下,上述这些文件,一般是放在项目的根目录下。此时它的默认作用域是对整个项目生效了。

但是在 monorepo 中,还是这么的简单方便吗?显然不是的。

这里我们以一个前端 yarn monorepo 为例:

// package.json "workspaces": { 
    "packages": [ "packages/*", "apps/*" ] } 

讯享网

其中 packages/* 中存放着所有的scope包,apps/* 表示所有的应用。

apps/* 中有 2 个项目,一个是 pc端->WebClient,另一个是移动端->MobileClient(以下简称WebMobile)。

显然,这两个项目的配置文件,有着极大的不同。比如 postcss.config.js 这个配置文件,我们在Mobile中引入了 viewport 自适应方案的插件,而Web端不需要,这造成了些许差别了。

此时显然把 postcss.config.js 放在 monorepo 的根目录是不恰当的,它需要跟着项目走。所以我们就可以在WebMobile中各放一个,再通过 preset 这种思想的方式,提炼公共插件即可。这时候配置文件的作用域就缩小,变成了 WebMobile 目录了。

假如有人问,为啥要分成2个端这样做,不能一套自适应吗?我的回答实际上也是可以的,比如你仅仅只需要把 postcss.config.js 变成 Function,然后判断一下传入路径,返回不同的配置即可,其余情况亦然。

hoist 机制下的问题

hoist 机制,npm/yarn/pnpm都有,它能够把多个 repo 中版本不冲突的共用模块,会被尽可能地提升至根路径。

yarn 默认开启 hoist 后,我们可以看到,WebMobile 安装的包,都被保存在了 根目录 下的 node_modules 中。

此时应用似乎能正常运行。

接下来我们分别在 MobileWeb 安装一些 UI Toolkit 包,同样,它们被提升到了根目录的 node_modules 中。但它们也能被正常的使用。

但是,由于 hoist 机制,UI Toolkit 包被提升后,它们不在项目的 postcss.config.js 作用范围内!

此时你使用 postcss-loader去处理,内部的 postcss-load-config加载到的配置文件,实际上是一个空对象!!!

如图所示:

监听 postcss-loader 中的 load-config部分代码

Image

注意加载的上下文和 load-config

Image

注意 hoist 后的文件路径和 load-config
Image

此时,假如有需求,要让 postcss 也走这样的配置,主要有 2 种方式:

  1. 取消 UI Toolkit 的提升机制
  2. 在根目录填充 postcss.config.js

显然,方法一比较符合我们的本意,所以我们需要做出如下修改:

讯享网 "workspaces": { 
    "packages": [ "packages/*", "apps/*" ], "nohoist": [ "/vant", "/element-plus" ] } 

这样就解决了这个问题。

同样这个机制也能解决 monorepo 中,多 vue/react版本的问题:

 "workspaces": { 
    "packages": [ "packages/*", "apps/*" ], "nohoist": [ "/react", "/vue" ] } 

这样你就可以愉快的同时启动 vue2vue3 项目了。

参考

postcss-load-config source code

yarn#nohoist in Workspaces

pnpm#public-hoist-pattern

小讯
上一篇 2025-01-14 21:18
下一篇 2025-03-24 15:39

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/57383.html