使用pnpm搭建monorepo

2,970 阅读2分钟

pnpm

新一代的包管理工具,和npmyarn对比优势在于:

  • 包安装速度快
  • 磁盘空间利用效率高 node_modules 中的所有文件均链接自单一存储位置
  • 支持monorepo 通过pnpm-workspace.yaml指定工作空间
  • 权限严格 pnpm 创建的 node_modules 默认并非扁平结构,因此代码无法对任意软件包进行访问

官网地址: www.pnpm.cn/

基本命令

首先执行npm install -g pnpm命令全局安装pnpm

-C , --dir

<path> 设置为 pnpm 的运行目录,而不是当前目录。比如说要运行指定工作空间命令

-w, --workspace-root

在根目录执行命令,比如说要在根目录安装指定npm

-F <package_name>,--filter <package_name>

可以通过pnpm --filter <package_selector> <command>命令过滤指定包运行命令

.npmrc

  • hoist 是否提升依赖
  • hoist-pattern 指定需要提升的包,默认全部提升
  • auto-install-peers 是否自动安装peerDependencies
  • strict-peer-dependenciespeerDependencies错误时,命令是否成功

版本管理

pnpm add -Dw @changesets/cli
pnpm changeset init
pnpm changeset
pnpm changeset version

搭建monorepo

根目录添加pnpm-workspace.yaml文件

packages:
  # all packages in direct subdirs of packages/
  - 'packages/*'
  # all packages in subdirs of components/
  - 'components/**'
  # exclude packages that are inside test directories
  - '!**/test/**'

monorepo 规范git commit 信息

假设我们有一个名为 @monorepo/project1 的子项目,我们针对该项目提交的 commit 信息可以写为:

git commit -m "feat(project1): 添加首页" 

可以通过commitlint检查commit信息是否符号约定的规范,使用commitizen自动生成规范的commit信息。

juejin.cn/post/699663…

遇到的问题

1. VsCode 中Vetur识别错误

image.png

解决办法:

在根目录新建vetur.config.js

module.exports = {
  settings: {
    "vetur.useWorkspaceDependencies": true,
    "vetur.experimental.templateInterpolationService": true
  },
  projects: [
    './packages/repo2', // Shorthand for specifying only the project root location
    {
      root: './packages/repo1',
      package: './package.json',
      tsconfig: './tsconfig.json',
      snippetFolder: './.vscode/vetur/snippets',
      globalComponents: [
        './src/components/**/*.vue'
      ]
    }
  ]
}

注:修改完后可能要重新打开工程

2. Vue中postcss.config.js识别问题

@vue/cli 4.5.4

默认会去加载根路径下的,不会识别当前工程中的配置。

|---- packages/
    |---- vue2    
          |---- postcss.config.js //不会被识别
          |---- package.json
          |---- vue.config.js  // 解决办法修改工程配置
|---- package.json
|---- postcss.config.js

vue.config.json cli.vuejs.org/zh/config/#…

module.exports = {
  css: {
    loaderOptions: {
      postcss: {
        config: {
          path: "./", // 指定配置文件读取位置,即`packages/vue2/postcss.config.js`
        },
        // 或者直接在这里写配置
        // plugins: [
        //   require("postcss-pxtorem")({
        //     rootValue: 153,
        //     propList: ["*"],
        //     exclude: /node_modules/,
        //   })
        // ]
      },
    },
  },
};

3. 当引入其它包时会报EsLint错误(npm link 导致eslint错误)

<template>
  <div class="home">
    <SiFooter />
  </div>
</template><script lang="ts">
import Vue from "vue";
import { SiFooter } from "@smart/themes"; // @ is an alias to /srcexport default Vue.extend({
  name: "Home",
  components: {
    SiFooter,
  },
});
</script>

image.png

这时因为使用pnpm引入monorepo其它包时是以符号链接添加到当前包,这时可能会导致eslintlink的包起作用了,即使exludenode_modules也会报错,因为webpack会把link的包resolve成他们的真实地址,所以就不受ignore限制了。

解决办法: 编写.eslintignore文件

**/themes  
**/包名

4. .eslintignore 识别问题

.eslintignore在二级目录时不生效,放到根目录才生效。

解决办法:

image.png

image.pngmarketplace.visualstudio.com/items?itemN…

参考:juejin.cn/post/709860…