facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.83k stars 26.88k forks source link

Force single resolution for peer dependencies on 'react' #12510

Open maritaria opened 2 years ago

maritaria commented 2 years ago

Is your proposal related to a problem?

(Write your answer here.)

Prevent a common, but hard to diagnose, problems with duplicate versions of react that occurs as a result of peer dependency resolution. Specifically when you link a local (development) version of a react component package into the application. This may for example present itself when developing a component library and including a demo project (made with CRA) in the library repository itself.

A common part of developer workflow for component libraries is to link the local version into consumer projects, for example by using yarn link.

The component library will have a peerDependencies entry for react, so it will be installed for development into the node_modules folder of the library. The process of yarn link creates a symlink of the package into one or more target projects. This often leads to loaders recognizing the package's own copy of react to be installed as the peer-dependency version for that library. The react library will then end up duplicated in the react application.

Describe the solution you'd like

A simple solution to this is using webpack aliasing, causing all resolutions for the 'react' module to be resolved to a specific path. This would then be the top-level version of react in the node_modules folder of the project.

Additionally a warning may be issued when a dependency has react installed as a peer dependency, which is not equivalent to the top level react library version. This may be challenging to implement as there are various ways that node_modules can be linked together through various tooling.

Describe alternatives you've considered

1. Manual linking

The current solution (specifically for yarn link) is to link the library consumer's react library into the dependencies of the library itself, or vice versa. This blog post details that solution step-by-step, which boils down to:

# 1. Register the library's react dependency for linking
(cd lib/node_module/react && yarn link)

# 2. Link the library's react dependency into the consumer project
(cd app && yarn link react)

2. Warning

Perhaps an easier type of warning to detect and issue would be to detect if in the module graph there are distinct modules named 'react', which would indicate that react would get loaded twice.

Additional context

The alias needs to use the full path to the react module, so peer dependencies are not accidentally resolved locally still.

const config = {
  alias: {
    'react': Path.join('/full/path/to/project/', '/node_modules/react'),
  },
};
maritaria commented 2 years ago

The required modification would need to affect the alias field of the webpack config: webpack.config.js#L322-332.

This would mean adding an entry among those that already exist, extending getWebpackAliases (which populates webpackAliases) or spreading in the result of a new function into webpackAliases.