-
Notifications
You must be signed in to change notification settings - Fork 194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
When inferring the module system (esm vs cjs) the nearest pacakge.jso… #771
Conversation
f00395f
to
f0576dd
Compare
var react_refresh__WEBPACK_IMPORTED_MODULE_0___namespace_cache; | ||
__webpack_require__.r(__webpack_exports__); | ||
/* harmony export */ __webpack_require__.d(__webpack_exports__, { | ||
/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) | ||
/* harmony export */ }); | ||
/* harmony import */ var react_refresh__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react-refresh */ \\"../../../../node_modules/react-refresh/runtime.js\\"); | ||
|
||
__webpack_require__.$Refresh$.runtime = react_refresh__WEBPACK_IMPORTED_MODULE_0__; | ||
__webpack_require__.$Refresh$.runtime = /*#__PURE__*/ (react_refresh__WEBPACK_IMPORTED_MODULE_0___namespace_cache || (react_refresh__WEBPACK_IMPORTED_MODULE_0___namespace_cache = __webpack_require__.t(react_refresh__WEBPACK_IMPORTED_MODULE_0__, 2))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
previously this test caused the react-refresh runtime to be injected with a import statement putting the module into esm mode. when imported into index.js (also ESM) the exports don't require any "conversion" so the load was simple.
Now the react-refresh runtime it's being injected with the plugin (it's excluded by the webpack config /node_modules/ rule) so it stays as a cjs module. Becasue of this webpack adds this translation code because we are crossing from cjs into esm land.
b52a494
to
f708a99
Compare
…n should be consulted from the point of the file. The current implemetation tracks the module system by rootContext but there may be package.json files deeper than the rootContext which alter the module system which should be used. If you have a folder inside an ESM project with a package.json containing `{ type: 'commonjs' }` then all .js files in that folder and descendents should be treated like cjs. This new implementation searches for package.json files from the point of the module being imported. to avoid doing any unecessary work the result is cached along the parent path of the module context (it's folder) so that you only need to look up as far as the nearest common folder that has already had a package.json resolved. Additionally the change removes a recently added bailout where the module system was assumed to be cjs if the LoaderContext's `this.environment` property was null. I believe this misunderstands the environment property and suggests that if it is not set then commonjs is an appropriate target. However it is possible to have a webpack config that does not produce an environment for the LoaderContext but is still an ESM project from src. Since the Loader runs before other transforms that might convert from ESM to CJS the module detection is still needed.
…Instead of feature testing with `this.environment` which was added to webpack 5 relatively recently use `typeof this.addMissingDepdencey === 'function'` which is in most (or all) webpack 5 releases but not included in webpack 4.
f708a99
to
9769038
Compare
Hey, sorry for ignoring this for so long - I'll give this a proper look this week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is amazing, thank you and sorry for holding off this for so long!
No worries, glad it landed. I wanted to update the react fixtures and now I will :) |
When inferring the module system (esm vs cjs) the nearest pacakge.json should be consulted from the point of the file. The current implementation tracks the module system by rootContext but there may be package.json files deeper than the rootContext which alter the module system which should be used. If you have a folder inside an ESM project with a package.json containing
{ type: 'commonjs' }
then all .js files in that folder and descendants should be treated like cjs. This new implementation searches for package.json files from the point of the module being imported. to avoid doing any unecessary work the result is cached along the parent path of the module context (it's folder) so that you only need to look up as far as the nearest common folder that has already had a package.json resolved.The
this.environment
feature test is updated to usetypeof this.addMissingDependency
instead.this.environment
was added to LoaderContext relatively recently and many versions of webpack 5 don't support that. Regardless of whether webpack 5 is outputting esm we need to use the esm form when the package type specifically opts into esm mode so we use a feature test that is exactly on the 4/5 boundary. This function is coincidentally also needed in the implementation too.I extended the cjs and esm fixtures to have a nested package.json with the alternate type to assert that when getting the module type for a nested resource the right version is picked up.
I updated the webpack config for
getCompilation
to exclude/node_modules/
. Previously the loader was processing the react-refresh runtime itself but these files are not part of local users project and are not the subject of hot reloading. A realistic webpack config would exclude these files in a real project so it seems appropriate to do so here. (If there is a reason why node_modules was not excluded I can remove this, it's doesn't affect the test results)I also added calls to
addDependency
andaddMissingDependency
to allow webpack to reload when a package.json changes or is added.