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

Parcel tries to import source of dependency instead of main or module even if it does not exist #7610

Closed
Systemcluster opened this issue Jan 26, 2022 · 3 comments · Fixed by #7846

Comments

@Systemcluster
Copy link

🐛 bug report

Parcel tries to resolve the source file of dependencies instead of the file specified by main or module even if the file referred to by source does not exist. This results in errors when importing a package that does not ship with source files.

🎛 Configuration (.babelrc, package.json, cli command)

Default configuration. Running parcel serve.

🤔 Expected Behavior

Parcel should import the file specified by main or module if the source file is not found.

😯 Current Behavior

Parcel always tries to resolve the source file of dependencies if it's specified. This fails when importing a package that does not ship with source files.

💁 Possible Solution

Use the main or module field during import resolution when appropriate.

It should be enough to filter entry points for existence in the NodeResolver:

--- a/packages/utils/node-resolver-core/src/NodeResolver.js
+++ b/packages/utils/node-resolver-core/src/NodeResolver.js
@@ -872,7 +872,10 @@ export default class NodeResolver {
           field: entry.field,
           filename: path.resolve(pkg.pkgdir, entry.filename),
         };
-      });
+      })
+      .filter(
+          entry => fs.existsSync(entry.filename)
+      );
   }
 
   async loadAsFile({

It's used by the DefaultResolver like so:

    const resolver = new NodeResolver({
      fs: options.inputFS,
      projectRoot: options.projectRoot,
      // Extensions are always required in URL dependencies.
      extensions:
        dependency.specifierType === 'commonjs' ||
        dependency.specifierType === 'esm'
          ? ['ts', 'tsx', 'js', 'jsx', 'json']
          : [],
      mainFields: ['source', 'browser', 'module', 'main'],
    });

(If this is the correct approach I can submit the change in a PR. I was not able to test this yet.)

🔦 Context

I am trying to import @radix-ui/react-scroll-area. This causes the build to fail:

× Build failed.

@parcel/core: Failed to resolve '@radix-ui/react-scroll-area' from './app/components/app.tsx'

  K:\Development\gh-dashboard\app\components\app.tsx:4:29
    3 | import styled from '@emotion/styled'
  > 4 | import * as ScrollArea from '@radix-ui/react-scroll-area'
  >   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    5 |
    6 | import { usePromise } from '../hooks/use-promise'

@parcel/resolver-default: Could not load './src/index.ts' from module '@radix-ui/react-scroll-area' found in
package.json#source

  K:\Development\gh-dashboard\node_modules\@radix-ui\react-scroll-area\package.json:5:13
    4 |   "license": "MIT",
  > 5 |   "source": "src/index.ts",
  >   |             ^^^^^^^^^^^^^^ './src/index.ts' does not exist, did you mean './dist/index.js'?'
    6 |   "main": "dist/index.js",
    7 |   "module": "dist/index.module.js",

💻 Code Sample

import * as ScrollArea from '@radix-ui/react-scroll-area'

🌍 Your Environment

Software Version(s)
Parcel 2.2.1
Node 17.4.0
npm/Yarn pnpm 6.28.0
Operating System Windows 10 21H2
@g6123
Copy link
Contributor

g6123 commented Mar 20, 2022

I have exactly the same issue using pnpm and Parcel.

@Systemcluster's solution seems nice, since it provides a gentle fallback logic, and thus does not require any additional configuration.

But at the same time, with such fallback, it would be quite confusing when users forgot to create the actual source file defined in package.json in the workspace in the same monorepo. Because the resolver would fallback to the browser, and main entry, it might resolve to the path of the output.

Here are some possible alternatives:

  • Testing with the package name. If the requested package name starts with the same prefix/scope as the project root AND is behind symlinks, then pick up the source entry.
  • Testing with the realpath. If the realpath of the symlink inlcudes node_modules (or maybe .pnpm?) then ignore source entry.

@g6123
Copy link
Contributor

g6123 commented Mar 20, 2022

I would personally prefer the second one, so made a PR of it #7846.
Any feedbacks are welcome 🙏

@g6123
Copy link
Contributor

g6123 commented Mar 20, 2022

..and I found a possible duplicate existing issue of this one a bit late. See also #5784.

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.

3 participants