react-async-ssr icon indicating copy to clipboard operation
react-async-ssr copied to clipboard

Error if module is compiled by webpack

Open Julia1996 opened this issue 4 years ago • 3 comments

Files for SSR are compiled by Webpack on our project. I am having the following error: isReactClassComponent is not a function in file shim.js. That is because Webpack prefer "module", not "main". If I change require('is-class-component') to require('is-class-component').default right in the shim.js file, it works fine. There is an issue in webpack repository https://github.com/webpack/webpack/issues/5756 where author of Webpack writes that module should export the same API in es module and in commonjs module. http://prntscr.com/xox5qg

How to reproduce: Create a module, use react-async-ssr in it and compile that module by Webpack.

Julia1996 avatar Jan 27 '21 05:01 Julia1996

+1 Adding .default worked

cgaxy avatar Feb 12 '21 13:02 cgaxy

Sorry for slow reply. Been busy with other projects.

Yes, adding .default would solve the problem in your case where you're bundling the code with Webpack. However, it would fail everywhere else because require('is-class-component') returns a function which doesn't have a .default property. So then using react-async-ssr unbundled from NodeJS would be broken, which is the most common use case.

This is a really thorny issue and there are no easy answers. Personally, I think Webpack's behavior is incorrect. If you require() a module it should use the main field, and if you import it should use module. Their assertion that every package should have a CommonJS export which is an object with a .default property is totally unrealistic. That's not how CommonJS works!

But I can also see the problem that Webpack is trying to solve - avoiding duplicate code in bundles where the same package is both require()-ed and import-ed in different places. In any case, by the looks of things, they're not going to change it, so whether they are correct or not is academic.

I understand Webpack 5 now supports the exports field in package.json. So perhaps the solution is to remove the module field from package.json entirely, so exports will be used instead, and that's already correctly configured.

Could I ask a favour: Could you please edit node_modules/is-class-component/package.json and remove the module field, then try building with Webpack again? (you might need to clear Webpack's cache to make sure it picks up the change)

I am also the maintainer of is-class-component so, if it works, I could make that change. I'm not sure how one could solve this problem if it was code under someone else's control.

From reading various issues in Webpack and ESBuild repos, it appears this is quite a common problem with various packages. Out of interest, have you run into this with any other packages?

overlookmotel avatar Mar 17 '21 02:03 overlookmotel

Sorry for slow reply. Been busy with other projects.

Yes, adding .default would solve the problem in your case where you're bundling the code with Webpack. However, it would fail everywhere else because require('is-class-component') returns a function which doesn't have a .default property. So then using react-async-ssr unbundled from NodeJS would be broken, which is the most common use case.

This is a really thorny issue and there are no easy answers. Personally, I think Webpack's behavior is incorrect. If you require() a module it should use the main field, and if you import it should use module. Their assertion that every package should have a CommonJS export which is an object with a .default property is totally unrealistic. That's not how CommonJS works!

But I can also see the problem that Webpack is trying to solve - avoiding duplicate code in bundles where the same package is both require()-ed and import-ed in different places. In any case, by the looks of things, they're not going to change it, so whether they are correct or not is academic.

I understand Webpack 5 now supports the exports field in package.json. So perhaps the solution is to remove the module field from package.json entirely, so exports will be used instead, and that's already correctly configured.

Could I ask a favour: Could you please edit node_modules/is-class-component/package.json and remove the module field, then try building with Webpack again? (you might need to clear Webpack's cache to make sure it picks up the change)

I am also the maintainer of is-class-component so, if it works, I could make that change. I'm not sure how one could solve this problem if it was code under someone else's control.

From reading various issues in Webpack and ESBuild repos, it appears this is quite a common problem with various packages. Out of interest, have you run into this with any other packages?

Hi! As a matter of fact, I forked this repository and added a .default on to the end of the import in shim.js as a gross hack and that worked for a while.

I've since done a fairly major upgrade to webpack and node, and my hack stopped working! reverting to use your library works without error...

I'm afraid my knowledge of webpack and node modules is pretty sketchy, but would be happy to provide info as needed!!

NathanRHD avatar May 22 '21 11:05 NathanRHD