头图

foreword

Some time ago, because the tool used in the Monorepo project used by the team was Lerna , so thinking about how to transform it, the final overall technology selection was PNPM + Changeset + Turborepo . Accordingly, it is necessary to support the capabilities of Lerna originally used in the context of this selection.

Among them, the more interesting is the need to publish the Package to the private Registry . Because, here Changeset is selected, so the last command to execute and publish will be:

 pnpm changeset publish

At this time, it involves a question, where should the private Registry in the project be configured? Here we are not in a hurry to find the answer, let's first understand the 4 postures of configuring a private registry.

1 Global registry

We can set the Global Registry by setting npm or pnpm of config , for example:

 # npm
npm config set registry=http://localhost:2000

# or pnpm
pnpm config set registry=http://localhost:2000

In this way, at the code level, the configuration here can be read through process.env.npm_config_registry .

2. npmrc

Whether it is npm or pnpm the configuration will be read from the project's .npmrc file by default, so when we need a private registry for package distribution, we can set it like this:

 registry = http://localhost:2000

3 --registry

When executing npm publish or pnpm publish , we can also bring the --registry Option to tell the corresponding package management tool what the registry is to publish the package. E.g:

 # npm
npm publish --registry=http://localhost:2000

# or pnpm
pnpm publish --registry=http://localhost:2000

4 PublishConfig

PublishConfig指的是我们可以publish命令的项目package.json中的publishConfig.registrynpm pnpm to publish, for example:

 {
  ...
  "publishConfig": {
    "registry": "http://localhost:2000"
  }
  ...
}

5 Changeset publish principle

After understanding the 4 postures of setting up a private registry, let's go back to the question at the beginning of the article, how to let pnpm changeset publish know to release the package to the specified private registry? If you think you can choose one of the above 4, then you may need to step on some pits.

First of all, what we need to know is pnpm changeset publish the essence of the command is to execute changeset publish . Then, that is, the above four ways of setting the Registry, it is very likely that not all of them will take effect, because Changeset has its own publish mechanism . In this process, it will mainly do three things:

1. First, get Package Info, it will get Package Info from the specified Registry . For example, if it is to get the Package Info of rollup , then it will be like this:

 npm info rollup --registry="https://registry.npmjs.org/" --json

2. Secondly, according to the versions field in the Package Info obtained above (it is an array containing all the released versions), compare the local package.json version field, to determine whether the current version has been released

3. Finally, if the current version is not released, the publish command will be executed according to the currently used package management tool, and a Registry address that it thinks should be released will be constructed at this time, and then rewritten env on the configuration, the corresponding code will be like this:

 // packages/cli/src/commands/publish/npm-utils
const envOverride = {
  npm_config_registry: getCorrectRegistry()
};
let { code, stdout, stderr } = await spawn(
  // 动态的包管理工具,例如 pnpm、npm、yarn
  publishTool.name,
  ["publish", opts.cwd, "--json", ...publishFlags],
  {
    env: Object.assign({}, process.env, envOverride)
  }
);

It can be seen that the whole process of changeset publish is still very simple and easy to understand. And, very importantly, what this process involves in the Registry is done by a function named getCorrectRegistry() , which is defined like this:

 // packages/cli/src/commands/publish/npm-utils.ts
function getCorrectRegistry(packageJson?: PackageJSON): string {
  const registry =
    packageJson?.publishConfig?.registry ?? process.env.npm_config_registry;

  return !registry || registry === "https://registry.yarnpkg.com"
    ? "https://registry.npmjs.org"
    : registry;
}

So looking at it, I think everyone understands why the four ways to set up the Registry mentioned above are probably not all effective.

因为,在Changeset 中只支持publishConfig f011f1d5121e82d819dfea0b95fc46b5---或---1e80c06844c63cf3b3cc7d595381df39 env Registry 的方式,所以如果你尝试其他2 种publishhttps://registry.yarnpkg.com or https://registry.npmjs.org , and the first step to get Package Info may fail.

Epilogue

I think the article is short, but the knowledge points conveyed are quite interesting. As for the PNPM + Changeset + Turborepo technology selection mentioned above, at least I'm still experiencing a very smooth experience, no matter in terms of dependency installation, multi-package task execution, Version Or Publish and so on. So, interested students can try it.

Finally, if there are inappropriate expressions or mistakes in the text, you are welcome to raise an Issue~

like

By reading this article, if you have gained something, you can give a like, this will become the motivation for me to continue to share, thank you~

I am Wuliu. I like to innovate and fiddle with source code. I focus on learning and sharing technologies such as source code (Vue 3, Vite), front-end engineering, and cross-end. Welcome to my WeChat public account Code center or GitHub .

五柳
1.1k 声望1.4k 粉丝

你好,我是五柳,希望能带给大家一些别样的知识和生活感悟,春华秋实,年年长茂。