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
feat(pwa-kit-dev): improve dependency resolving for findInProjectThenSDK
#978
base: v2-archive-20230512
Are you sure you want to change the base?
Conversation
Hacky way to test drive the mono repository logic: install |
* Find the path to a dependency | ||
* First check the project's node_modules, then the SDK's node_modules, then the monorepo's node_modules |
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.
I don't know the history of this method, but it seems like the goal is "If node's module resolution can't find the package, check this other location as a fallback." To that end, why not just leverage node's built-ins? Something like
try {
return require.resolve(pkg)
} catch (err) {
const sdkPath = resolve(sdkDir, 'node_modules', pkg)
if (fs.existsSync(sdkPath)) return sdkPath
else throw err
}
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.
+1. TIL require.resolve
. Here's an article that talks about it: https://dev.to/stephencweiss/what-is-require-resolve-and-how-does-it-work-1ho4
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.
Late to the party. But I think there is an opportunity to simplify things even more.
Going back, the history of that function was to solve a problem we created for ourselves by using a lerna mono repo that doesn't use it's main feature, hoisting dependencies (I believe that there was a reason why we chose not to hoist, but I can't remember).
Because of the decision not to hoist we continually ran into problems where modules that have global context like react-helmet
or react-loadable
didn't work 100% because the sdk was using one instance of the module and the pwa template was using another. So to solve this we used webpack alias's and that funky little utility called findInProjectThenSDK
, at the time we didn't think of using resolve as we know where the dependencies were. So we can make things better by using that as you suggest @wjhsf, but what if we did something a little more daring....
What if we decided to start hoisting our deps? or replace lerna with npm workspaces. Doing this would solve the root problem so we didn't need special functions to find modules, internally the npm module resolution would kinda just work 🤞 Sounds simple, probably isn't going to be. But I think it's better than what we have now.
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.
I did a proof of concept where I generated and placed it in a npm workspace project and ripped out the findInProjectThenSDK
and a few other minor changes and was able to get things working. So there is some promise.
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.
@bendvc Template Extensibility uses findInProjectThenInSDK
(and modifies it). Can you share what you were working on so I can make sure it works for the new feature?
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.
Thanks @ecRobertEngel for this PR. It does reveal a few bugs with our current implementation and also a feature request to support monorepo too.
if (fs.existsSync(sdkPath)) { | ||
return sdkPath | ||
} | ||
if (isMonoRepo) { |
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.
As you mentioned in your PR description, I don't think we have considered the scenario of developers having their own monorepo. So I'd consider this to be a new feature.
However, there is a bug with the current implementation: for those developers who do not have a monorepo, the sdkDir
is actually not resolved correctly.
const sdkDir = resolve(path.join(__dirname, '..', '..', '..')) |
The above line would resolve correctly only for those folks developing PWA Kit:
- Within PWA Kit monorepo:
packages/pwa-kit-dev/src/configs/webpack/config.js
→sdkDir
is mapped topackages/pwa-kit-dev/
- Within a generated project (and no monorepo):
node_modules/pwa-kit-dev/configs/webpack/config.js
→sdkDir
is mapped tonode_modules
(and notnode_modules/pwa-kit-dev/
)
return monoRepoPath | ||
} | ||
} | ||
throw new Error(`Could not find dependency ${pkg}`) |
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.
You mentioned a few dependencies that don't seem to exist anywhere. One of them is react-query
. It actually can be found in pwa-kit-react-sdk
package, but not the pwa-kit-dev
.
Again, I think there's another bug with sdkDir
. It equates 'sdk' to mean pwa-kit-dev
, where in fact we may want to check the other pwa-kit-related packages too. I think this is a regression when we moved to V2 of PWA Kit. In V1, there used to be only pwa-kit-react-sdk, but in V2 we split it into smaller packages.
* @param {string} pkg - name of the dependency | ||
* @returns {string} path to the dependency | ||
*/ | ||
const findDependency = (pkg) => { | ||
const projectPath = resolve(projectDir, 'node_modules', pkg) |
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.
I think to be aligned with the original intention (find in project first and then in the sdk), I would check isMonoRepo
earlier in the code block.
const projectPath = resolve(projectDir, 'node_modules', pkg) | |
const projectPath = isMonoRepo ? resolve(projectDir, '..', '..', 'node_modules', pkg) : resolve(projectDir, 'node_modules', pkg) |
findInProjectThenSDK
This issue has been linked to a new work item: W-12539749 |
@ecRobertEngel any update on this? We've labeled this a regression and are tracking internally. Need to know the status |
@bfeister we have replace the build logic for this completely as it did not fit our setup at all. I would need to setup a new project to see the current status of this issue. I did not track the changes that are done as part of the the extensibility poc and if they can resolve this. |
Description
This PR tries to improve dependency resolving of the webpack configuration. I also have some questions and I am looking for your feedback for that.
Why this change
The current logic of
findInProjectThanSdk
has a few problems:babel-runtime
@tanstack/react-query
andhtml-loader
are all not resolved by this logic. This can cause very confusing behavior.Solution Approach
I tried to make the solution both more flexible and robust:
Next steps
The PR in it's current stage will not build a project successfully. This is because the added error throws if a dependency could not be resolved. In my opinion this should be the correct behavior as everything else will just cause issues down the line. But please provide me some feedback on this. In the meantime I think it makes sense to check why these dependencies are not resolved and how to move forward:
babel-runtime
@tanstack/react-query
html-loader
Types of Changes
Changes
How to Test-Drive This PR
Checklists
General
Accessibility Compliance
You must check off all items in one of the follow two lists:
or...
Localization