Skip to content
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

package.json#source field is used for npm packages with pnpm #5784

Closed
mischnic opened this issue Feb 5, 2021 · 11 comments · Fixed by #7846
Closed

package.json#source field is used for npm packages with pnpm #5784

mischnic opened this issue Feb 5, 2021 · 11 comments · Fixed by #7846

Comments

@mischnic
Copy link
Member

mischnic commented Feb 5, 2021

🐛 bug report

When using pnpm, the resolver tries to use the "source" field of a package from npm.

😯 Current Behavior

🚨 Build failed.
@parcel/core: Failed to resolve 'compute-scroll-into-view' from './index.js'
/index.js:1:35
> 1 | import computeScrollIntoView from "compute-scroll-into-view";
>   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
  2 |
  3 | computeScrollIntoView();
@parcel/resolver-default: Could not load './src/index.ts' from module 'compute-scroll-into-view' found in package.json#source
/node_modules/compute-scroll-into-view/package.json:88:13
  87 |   },
> 88 |   "source": "src/index.ts",
>    |             ^^^^^^^^^^^^^^ './src/index.ts' does not exist, did you mean './dist/index.js'?'
  89 |   "umd:main": "umd/compute-scroll-into-view.min.js"
  90 | }

🤔 Expected Behavior

Ignore package.json#source for npm packages

🔦 Context

#5604 (comment)

💻 Code Sample

import computeScrollIntoView from "compute-scroll-into-view";

computeScrollIntoView();
{
  "dependencies": {
    "@babel/core": "^7.12.13",
    "compute-scroll-into-view": "^1.0.16"
  }
}

Use pnpm install!

🌍 Your Environment

Software Version(s)
Parcel 31f431d
@ngfk
Copy link

ngfk commented Feb 17, 2021

@mischnic Did you find a workaround for this issue? I'm also trying to load compute-scroll-into-view in a pnpm + parcel2 project.

@mischnic
Copy link
Member Author

I don't think there is a workaround, unfortunately.

This is the problematic code

// If the package has a `source` field, check if it is behind a symlink.
// If so, we treat the module as source code rather than a pre-compiled module.
if (pkg.source) {
let realpath = await this.fs.realpath(file);
if (realpath === file) {
delete pkg.source;
}
}

Until pnpm, symlinks meant that you're using a monorepo and you're not importing an npm package but another monorepo package. The condition should probably be adjusted to make pnpm work.

@ngfk
Copy link

ngfk commented Feb 17, 2021

Maybe something like this? This is very specific to pnpm though.

if (realpath === file || realpath.includes('node_modules/.pnpm'))
  delete pkg.source;

@mischnic
Copy link
Member Author

Or maybe something like "if it's a symlink and the realpath is inside of the project root"

@ngfk
Copy link

ngfk commented Feb 17, 2021

Isn't everything in the project root? Unless you meant the node_modules of the project root, that could work.

if (realpath === file || realpath.startsWith(path.join(this.projectRoot, 'node_modules')))
  delete pkg.source;

@mischnic
Copy link
Member Author

Don't the pnpm symlinks point to a global folder like /Users/abc/.pnpm/....?

@ngfk
Copy link

ngfk commented Feb 17, 2021

You're right I had to Google around to check. But pnpm works with a content-addressable store /Users/abc/.pnpm-store, and a virtual store node_modules/.pnpm. After an install it mentions that packages are hard linked from the content-addressable store to the virtual store.

Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: /Users/ngfk/.pnpm-store/v3
  Virtual store is at:             node_modules/.pnpm
Progress: resolved 951, reused 950, downloaded 1, added 954, done

In my case (macOS) the realpath resolved to the location in the virtual store. Not sure if it's the same on a Windows machine. Here's an example of what I get in my project when I simply add a console.log(realpath) to the function.

console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/package/client/package.json
console: /Users/ngfk/Repositories/bce-module-manager/node_modules/.pnpm/[email protected]/node_modules/compute-scroll-into-view/package.json
console: /Users/ngfk/Repositories/bce-module-manager/node_modules/.pnpm/@parcel/[email protected]/node_modules/@parcel/runtime-js/package.json
console: /Users/ngfk/Repositories/bce-module-manager/node_modules/.pnpm/@parcel/[email protected]/node_modules/@parcel/runtime-js/package.json
console: /Users/ngfk/Repositories/bce-module-manager/node_modules/.pnpm/@parcel/[email protected]/node_modules/@parcel/runtime-js/package.json
console: /Users/ngfk/Repositories/bce-module-manager/node_modules/.pnpm/@parcel/[email protected]/node_modules/@parcel/runtime-js/package.json
console: /Users/ngfk/Repositories/bce-module-manager/node_modules/.pnpm/@parcel/[email protected]/node_modules/@parcel/runtime-js/package.json
console: /Users/ngfk/Repositories/bce-module-manager/node_modules/.pnpm/@parcel/[email protected]/node_modules/@parcel/runtime-js/package.json

@baronnoraz
Copy link

baronnoraz commented Feb 17, 2021

Yes, it's in /Users/abc/.pnpm-store/. However that can be changed using

npm config set store-dir /path/to/.pnpm-store

I think a .modules.yml file can also be stored in the node_modules to redirect you to a different location as well. I've read about that, but never used it.

I actually use Rush to manage my monorepo, and I have it using pnpm. The final destination for the dependencies is .../project-xyz/common/temp/node_modules/.pnpm/node_modules. But I think pnpm actually saves the dependencies in sibling folders corresponding to the repository names to which node_modules is linked.

.../project-xyz/common/temp/node_modules/.pnpm/node_modules (symlinks to the other two folders)
.../project-xyz/common/temp/node_modules/.pnpm/npm.fontawesome.com
.../project-xyz/common/temp/node_modules/.pnpm/registry.npmjs.org

@ngfk
Copy link

ngfk commented Jul 21, 2021

Is there something I can do to help get a fix for this issue? I'm still running into packages that parcel incorrectly tries to resolve using package.json#source.

@statianzo
Copy link

For this package specifically, adding "compute-scroll-into-view": "compute-scroll-into-view/dist" under "alias" in package.json solved the issue.

@guesant
Copy link

guesant commented Dec 9, 2021

Maybe something like this? This is very specific to pnpm though.

if (realpath === file || realpath.includes('node_modules/.pnpm'))
  delete pkg.source;

I made a small Proof-Of-Concept ParcelJS Resolver based on your solution + DefaultResolver, it seems to fix my issues by now:

https:/guesant/parcel-resolver-pnpm/blob/c1caa7aea03bead33e43685fb8c8968984d533a1/src/PNPMResolver.ts#L34-L42


Usage:

pnpm i parcel-resolver-pnpm

Partial .parcelrc file:

{
  "resolvers": [
    "parcel-resolver-pnpm",
    "..."
  ]
}

Here is the project repository: https:/guesant/parcel-resolver-pnpm

NPM | unpkg browse

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants