webpack icon indicating copy to clipboard operation
webpack copied to clipboard

NormalModuleReplacementPlugin doesn't resolve relative imports of also replaced modules within replaced modules anymore in webpack 5

Open Johennes opened this issue 2 years ago • 4 comments

Bug report

What is the current behavior?

Apologies for the cryptic title but I'm not sure how to describe this better. I fear what follows below might not be much easier to understand either, sadly.

We're using NormalModuleReplacementPlugin in element-web to replace files within matrix-react-sdk (which is in node_modules) with files from element-web: https://github.com/vector-im/element-web/blob/develop/webpack.config.js#L79 (the replacement map is read from https://github.com/vector-im/element-web/blob/develop/components.json)

Some of the replaced-with files import other replaced-with files. E.g. VectorAuthPage from element-web (which replaces AuthPage from matrix-react-sdk) imports VectorAuthFooter from element-web (which replaces AuthFooter from matrix-react-sdk): https://github.com/vector-im/element-web/blob/develop/src/components/views/auth/VectorAuthPage.tsx#L20

This has worked fine up until the latest current version of Webpack 4 but stopped working in Webpack 5. With:

new webpack.NormalModuleReplacementPlugin(
	new RegExp(oldPath.replace(/\//g, "[\\/\\\\]").replace(/\./g, "\\.")),
	path.resolve(__dirname, newPath))

we're now hitting this error

[webpack-cli] ModuleNotFoundError: Module not found: Error: Can't resolve './VectorAuthFooter' in '/Users/jm/Code/element-web/node_modules/matrix-react-sdk/src/components/views/auth'

Note how it tries to look for VectorAuthFooter (which is imported from VectorAuthPage and in element-web) in matrix-react-sdk/src/components/views/auth (which is the parent directory of the replaced file AuthFooter in matrix-react-sdk).

To get it to work, we have to manually set the context now as in:

new webpack.NormalModuleReplacementPlugin(
	new RegExp(oldPath.replace(/\//g, "[\\/\\\\]").replace(/\./g, "\\.")),
	function (resource) {
	    resource.request = path.resolve(__dirname, newPath);
	    resource.createData.resource = path.resolve(__dirname, newPath);
	    console.log(resource)
	    // Starting with Webpack 5 we also need to set the context as otherwise replacing
	    // files in e.g. matrix-react-sdk with files from element-web will try to resolve
	    // them within matrix-react-sdk
	    /resource.context = path.dirname(resource.request)
	    resource.createData.context = path.dirname(resource.createData.resource);
	  }

If the current behavior is a bug, please provide the steps to reproduce.

What is the expected behavior?

Setting context manually should not be necessary.

Other relevant information:

webpack version: 5.88.2 Node.js version: 18.16.1 Operating System: macOS Additional tools:

Johennes avatar Sep 29 '23 20:09 Johennes

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

webpack-bot avatar Dec 30 '23 11:12 webpack-bot

Sorry for delay, can you provide a small reproducible example?

alexander-akait avatar Jan 04 '24 15:01 alexander-akait

I got the same issue with the webpack v5. NormalModuleReplacementPlugin is not replacing the file anymore. As mentioned, I had to use at least these two lines to make it work.

resource.request = path.resolve(__dirname, newPath);
resource.createData.resource = path.resolve(__dirname, newPath);

antoantonydh avatar Jan 24 '24 15:01 antoantonydh

@antoantonydh Can you create reproducible test repo? Thank you

alexander-akait avatar Jan 26 '24 14:01 alexander-akait

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

webpack-bot avatar May 12 '24 09:05 webpack-bot