зеркало из https://github.com/microsoft/rnx-kit.git
docs(metro-plugin-duplicates-checker): add section about deduping (#2941)
This commit is contained in:
Родитель
7aae48f047
Коммит
f82018c955
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
---
|
|
@ -61,3 +61,171 @@ checkForDuplicatePackages(mySourceMap, {
|
|||
| bannedModules | string[] | `[]` | List of modules that are banned. |
|
||||
| ignoredModules | string[] | `[]` | List of modules that can be ignored. |
|
||||
| throwOnError | boolean | `true` | Whether to throw when duplicates are found. |
|
||||
|
||||
## Resolving Duplicates
|
||||
|
||||
So you have duplicates in your bundle, now what? Depending on your specific
|
||||
needs, we have several options.
|
||||
|
||||
Let's use a specific example:
|
||||
|
||||
```
|
||||
error @fluentui-react-native/text (found 2 copies)
|
||||
warn 0.21.14 /~/node_modules/@fluentui-react-native/text
|
||||
warn 0.22.7 /~/node_modules/@fluentui-react-native/link/node_modules/@fluentui-react-native/text
|
||||
```
|
||||
|
||||
This one occurs because `@fluentui-react-native/link` declares a dependency on
|
||||
`@fluentui-react-native/text` using a wide version range, `>=0.21.14 <1.0.0`.
|
||||
|
||||
Our project depends on `@fluentui-react-native/text@^0.21.14`, but package
|
||||
managers will typically still try to resolve `>=0.21.14 <1.0.0` instead of using
|
||||
the existing resolution. This results in the duplicate error we see above.
|
||||
|
||||
From here, we have several options:
|
||||
|
||||
- [Manual Dedupe](#manual-dedupe)
|
||||
- [Using Tools](#using-tools)
|
||||
- [Help Metro Resolve Correct Version](#help-metro-resolve-correct-version)
|
||||
- [Last Resort: Force Resolution](#last-resort-force-resolution)
|
||||
|
||||
### Manual Dedupe
|
||||
|
||||
This method is error-prone, especially if you have a lot of duplicates. It works
|
||||
if you have very few entries. It varies a lot depending on the package manager
|
||||
you're using.
|
||||
|
||||
The project in our example uses Yarn Classic: Open `yarn.lock` and look for
|
||||
`@fluentui-react-native/text`:
|
||||
|
||||
```yaml
|
||||
"@fluentui-react-native/text@0.21.14", "@fluentui-react-native/text@^0.21.14":
|
||||
version "0.21.14"
|
||||
resolved "https://registry.yarnpkg.com/@fluentui-react-native/text/-/text-0.21.14.tgz#04918a9558770ec551cbdac87ca1534bfccaeffb"
|
||||
integrity sha1-BJGKlVh3DsVRy9rIfKFTS/zK7/s=
|
||||
dependencies:
|
||||
"@fluentui-react-native/adapters" ">=0.11.3 <1.0.0"
|
||||
"@fluentui-react-native/framework" "0.11.10"
|
||||
"@fluentui-react-native/interactive-hooks" ">=0.24.12 <1.0.0"
|
||||
"@fluentui-react-native/theme-tokens" ">=0.25.4 <1.0.0"
|
||||
"@fluentui-react-native/tokens" ">=0.21.6 <1.0.0"
|
||||
"@uifabricshared/foundation-compose" "^1.14.12"
|
||||
tslib "^2.3.1"
|
||||
|
||||
"@fluentui-react-native/text@>=0.21.14 <1.0.0":
|
||||
version "0.22.7"
|
||||
resolved "https://registry.yarnpkg.com/@fluentui-react-native/text/-/text-0.22.7.tgz#bd11768d3cd69337ad2ec4be76ee88d6749ca24f"
|
||||
integrity sha1-vRF2jTzWkzetLsS+du6I1nScok8=
|
||||
dependencies:
|
||||
"@fluentui-react-native/adapters" ">=0.12.0 <1.0.0"
|
||||
"@fluentui-react-native/framework" "0.13.6"
|
||||
"@fluentui-react-native/interactive-hooks" ">=0.25.7 <1.0.0"
|
||||
"@fluentui-react-native/theme-tokens" ">=0.26.5 <1.0.0"
|
||||
"@fluentui-react-native/tokens" ">=0.22.5 <1.0.0"
|
||||
"@uifabricshared/foundation-compose" "^1.14.20"
|
||||
tslib "^2.3.1"
|
||||
```
|
||||
|
||||
We can see there are two entries, one being resolved to 0.21.14 and the other to
|
||||
0.22.7. In this case, since we want to keep 0.21.x and the version ranges just
|
||||
happens to be satisfied by this. We can merge the two entries like below:
|
||||
|
||||
```yaml
|
||||
"@fluentui-react-native/text@0.21.14", "@fluentui-react-native/text@>=0.21.14 <1.0.0", "@fluentui-react-native/text@^0.21.14":
|
||||
version "0.21.14"
|
||||
resolved "https://registry.yarnpkg.com/@fluentui-react-native/text/-/text-0.21.14.tgz#04918a9558770ec551cbdac87ca1534bfccaeffb"
|
||||
integrity sha1-BJGKlVh3DsVRy9rIfKFTS/zK7/s=
|
||||
dependencies:
|
||||
"@fluentui-react-native/adapters" ">=0.11.3 <1.0.0"
|
||||
"@fluentui-react-native/framework" "0.11.10"
|
||||
"@fluentui-react-native/interactive-hooks" ">=0.24.12 <1.0.0"
|
||||
"@fluentui-react-native/theme-tokens" ">=0.25.4 <1.0.0"
|
||||
"@fluentui-react-native/tokens" ">=0.21.6 <1.0.0"
|
||||
"@uifabricshared/foundation-compose" "^1.14.12"
|
||||
tslib "^2.3.1"
|
||||
```
|
||||
|
||||
Now we should only have one copy of `@fluentui-react-native/text`.
|
||||
|
||||
Our example is relatively simple. Sometimes you have to go further up the
|
||||
dependency chain and dedupe dependees.
|
||||
|
||||
Fortunately, we can use tools in most cases.
|
||||
|
||||
### Using Tools
|
||||
|
||||
If you're using Yarn Classic, there is a tool, [`yarn-deduplicate`][], for
|
||||
deduplicating everything in `yarn.lock`. You can run it like so:
|
||||
|
||||
```sh
|
||||
npx yarn-deduplicate
|
||||
```
|
||||
|
||||
By default, it will try to dedupe to the highest version. In our example,
|
||||
however, we want to keep using 0.21.x. We should also limit the number of
|
||||
packages that get deduped to make it easier to review later. `yarn-deduplicate`
|
||||
provides many options, but we'll be using the `fewer` strategy and the
|
||||
`--scopes` flag to only target `@fluentui-react-native` packages:
|
||||
|
||||
```sh
|
||||
npx yarn-deduplicate --strategy fewer --scopes @fluentui-react-native
|
||||
```
|
||||
|
||||
You can read more about `yarn-deduplicate` and available options here:
|
||||
https://github.com/scinos/yarn-deduplicate#readme
|
||||
|
||||
If you're using modern Yarn or other package managers, check out their built-in
|
||||
dedupe command:
|
||||
|
||||
- **Yarn:** https://yarnpkg.com/cli/dedupe
|
||||
- **npm:** https://docs.npmjs.com/cli/commands/npm-dedupe
|
||||
- **pnpm:** https://pnpm.io/cli/dedupe
|
||||
|
||||
### Help Metro Resolve Correct Version
|
||||
|
||||
If, for some reason, you cannot dedupe the package, you can instead configure
|
||||
Metro to resolve the correct version by telling it which version to use (with
|
||||
[`resolver.extraNodeModules`][]) and blocking every other copy (with
|
||||
[`resolver.blockList`][]):
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
resolver: {
|
||||
extraNodeModules: {
|
||||
"@fluentui-react-native/text":
|
||||
"/~/my-project/node_modules/@fluentui-react-native/text",
|
||||
},
|
||||
blockList: [
|
||||
/(?<!\/~\/my-project)\/node_modules\/@fluentui-react-native\/text\/.*/,
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
You don't have to write these entries manually. We have helper functions in
|
||||
[`@rnx-kit/metro-config`][] for generating them dynamically.
|
||||
|
||||
### Last Resort: Force Resolution
|
||||
|
||||
As a last resort, if everything else fails, you can manually override package
|
||||
resolutions. We don't recommend this solution because it forces a single version
|
||||
in all workspaces. For example, if you have two projects that have nothing to do
|
||||
with each other, they will both be forced to use the same version even though
|
||||
they could be using different versions. It also adds maintenance overhead
|
||||
because you will have to manually update the version as dependees update theirs.
|
||||
|
||||
If you've decided that you have no other options, you can find the appropriate
|
||||
documentation for your package manager below:
|
||||
|
||||
- **Yarn:** https://yarnpkg.com/configuration/manifest#resolutions
|
||||
- **npm:** https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
|
||||
- **pnpm:** https://pnpm.io/package_json#pnpmoverrides
|
||||
|
||||
<!-- References -->
|
||||
|
||||
[`@rnx-kit/metro-config`]:
|
||||
https://github.com/microsoft/rnx-kit/blob/main/packages/metro-config/README.md#ensuring-a-single-instance-of-a-package
|
||||
[`resolver.blockList`]: https://metrobundler.dev/docs/configuration/#blocklist
|
||||
[`resolver.extraNodeModules`]:
|
||||
https://metrobundler.dev/docs/configuration/#extranodemodules
|
||||
[`yarn-deduplicate`]: https://github.com/scinos/yarn-deduplicate
|
||||
|
|
Загрузка…
Ссылка в новой задаче