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

Support Yarn 2 link protocol aliases #2825

Open
swandir opened this issue Apr 2, 2021 · 9 comments
Open

Support Yarn 2 link protocol aliases #2825

swandir opened this issue Apr 2, 2021 · 9 comments

Comments

@swandir
Copy link
Contributor

swandir commented Apr 2, 2021

Clear and concise description of the problem

Yarn 2 offers the link protocol as a tool-agnostic way to configure aliases:
https://yarnpkg.com/features/protocols/#why-is-the-link-protocol-recommended-over-aliases-for-path-mapping

{
  "dependencies": {
    "src": "link:./src"
  }
}

The problem is that Vite tries to pre-bundle the linked directory as a dependency

error when starting dev server:
Error: The following dependencies are imported but could not be resolved:

  src/<path> (imported by <path>)

Suggested solution

Vite could recognize this pattern by either:

Alternative

As a work-around this works:

export default defineConfig({
  optimizeDeps: {
    exclude: ["src"],
  },
});

UPDATE: it doesn't work. But resolve.alias can be used instead.

But it'd be nicer to have this handled automatically.

Additional context

@github-actions
Copy link

github-actions bot commented Apr 2, 2021

Hello @swandir. We totally like your proposal/feedback, welcome to send us a Pull Request for it. Please provide changelog/TypeScript/documentation/test cases if needed and make sure CI passed, we will review it soon. We appreciate your effort in advance and looking forward to your contribution!

@Shinigami92 Shinigami92 added enhancement New feature or request and removed enhancement: pending triage labels Apr 2, 2021
@swandir
Copy link
Contributor Author

swandir commented Apr 3, 2021

So I looked in this a bit more and found that

  1. Vite actually doesn't optimize linked deps by default, but
  2. it expects every linked directory to contain package.json.

Also, the workaround does not work, because Vite fails to resolve modules from a linked directory at runtime anyway.

I don't think it was specified explicitly before, but now Yarn states that the "link:" protocol does not require a directory to be a valid package.

Anyway, currently

  • NPM does not support "link:";
  • PNPM crashes the install if a "link:"-ed directory does not contain package.json;
  • Yarn 1 allows "link:"-ed directories without package.json, but installs transitive dependencies if it finds package.json;
  • Yarn 2 does not consider package.json in "link:"-ed directories at all.

The difference between Yarn 1 and 2 wouldn't affect Vite if it relied on package.json through "resolve" only, but Vite looks for other metadata in package.json as well.

Yarn 2's interpretation of "link:"-deps is something more like [subpath imports](node resolution algorithm), except the linked directory doesn't have to be located within the one it's referenced by. Which makes locating package.json that owns the linked directory tricky.

Not sure how this could be implemented in Vite and whether it really is worth pursuing.

@drazik
Copy link

drazik commented Oct 25, 2021

Is anything planned to fix this? It would be awesome if Vite worked with this Yarn feature. It makes alias tool-agnostic. Currently I have it enabled and working for multiple tools, but it fails in Vite, so I have to manually duplicate aliases in vite.config.ts.

I would be happy to help if possible, but I am a newcomer so I will need help entering Vite's codebase I think.

@lensbart
Copy link

lensbart commented Jun 5, 2022

Agreed that it would be nice to have this fixed.

A temporary workaround, in my case, is to set

{
  "compilerOptions": {
    "baseUrl": ".", // awaiting fix: https://github.com/vitejs/vite/issues/2825
  }
}

in tsconfig.json.

@seivan
Copy link

seivan commented Jul 6, 2022

Yeah, I second this.
The idea that the main guy who knows how to get all the packages, is responsible for getting your set of packages just sits well with me.

Instead of various third party libs, letting the main resolver, doing the resolving is actually pretty brilliant, especially since it's baked in and such a fundamental part of your toolkit.

@lensbart Would you mind sharing a bit more? I haven't managed to get it to work beyond writing a resolver for hand in vite config and writing resolve.alias kinda defeats the purpose.

Plus "baseUrl": "./src", in tsconfig.

Then I just import using whatever dir is under src

import x form "underSrc/something".

I am content with it even starting from src like

import x form "src/underSrc/something".

@swandir
Copy link
Contributor Author

swandir commented Jul 6, 2022

#7385 might be a better alternative overall

@seivan
Copy link

seivan commented Jul 6, 2022

#7385 might be a better alternative overall

As long as it doesn't require repeating or spreading source.
What I liked about yarns approach was, that it was in a single place, not even compilerOptions would need it.

If it's going to be with module maps, I am hoping its generated from whatever the source is. Either TS or Yarn.

@merceyz
Copy link
Contributor

merceyz commented Nov 11, 2022

From #2825 (comment) @swandir

NPM does not support "link:";

While that is true it does support file: which achieves the same thing.

PNPM crashes the install if a "link:"-ed directory does not contain package.json;

This was fixed in pnpm v7.

@rtritto
Copy link

rtritto commented Apr 25, 2023

@merceyz any update?

With:

vite.config.ts

export default defineConfig({
  root: 'src'
})

Output:

error when starting dev server:
Error: Cannot find module <first_dependency_in_package.json>
Require stack:
- package.json
    at Module._resolveFilename (node:internal/modules/cjs/loader:1090:15)
    at require$$0.Module._resolveFilename (C:\<PROJECT_PATH>\.pnp.cjs:15306:46)
    at callNativeResolution (C:\<PROJECT_PATH>\.pnp.cjs:16556:30)
    at resolveToUnqualified (C:\<PROJECT_PATH>\.pnp.cjs:16714:24)
    at Object.resolveToUnqualified (C:\<PROJECT_PATH>\.pnp.cjs:17014:26)
    at findDepPkgJsonPath (file:///C:/<PROJECT_PATH>/.yarn/__virtual__/vitefu-virtual-1a71c6a3cd/3/Users/Computer/AppData/Local/Yarn/Berry/cache/vitefu-npm-0.2.4-12a4de4ebd-9.zip/node_modules/vitefu/src/index.js:199:25)
    at file:///C:/<PROJECT_PATH>/.yarn/__virtual__/vitefu-virtual-1a71c6a3cd/3/Users/Computer/AppData/Local/Yarn/Berry/cache/vitefu-npm-0.2.4-12a4de4ebd-9.zip/node_modules/vitefu/src/index.js:150:36
    at Array.map (<anonymous>)
    at crawl (file:///C:/<PROJECT_PATH>/.yarn/__virtual__/vitefu-virtual-1a71c6a3cd/3/Users/Computer/AppData/Local/Yarn/Berry/cache/vitefu-npm-0.2.4-12a4de4ebd-9.zip/node_modules/vitefu/src/index.js:149:27)
    at crawlFrameworkPkgs (file:///C:/<PROJECT_PATH>/.yarn/__virtual__/vitefu-virtual-1a71c6a3cd/3/Users/Computer/AppData/Local/Yarn/Berry/cache/vitefu-npm-0.2.4-12a4de4ebd-9.zip/node_modules/vitefu/src/index.js:49:9)

With:

vite.config.ts

export default defineConfig({
  root: path.join(process.cwd(), 'src'),
})

package.json

  "configs": "link:./src/configs"

Output:

Error: ENOENT: no such file or directory, open 'C:\<PROJECT_PATH>\src\configs\package.json'
    at Object.openSync (node:fs:589:3)
    at NodeFS.openSync (C:\<PROJECT_PATH>\.pnp.cjs:11296:24)
    at makeCallSync.subPath.subPath (C:\<PROJECT_PATH>\.pnp.cjs:11723:26)
    at ZipOpenFS.makeCallSync (C:\<PROJECT_PATH>\.pnp.cjs:12358:14)
    at ZipOpenFS.openSync (C:\<PROJECT_PATH>\.pnp.cjs:11722:17)
    at VirtualFS.openSync (C:\<PROJECT_PATH>\.pnp.cjs:11044:24)
    at PosixFS.openSync (C:\<PROJECT_PATH>\.pnp.cjs:11044:24)
    at NodePathFS.openSync (C:\<PROJECT_PATH>\.pnp.cjs:11044:24)
    at Object.readFileSync (node:fs:457:35)
    at NodeFS.readFileSync (C:\<PROJECT_PATH>\.pnp.cjs:11585:24)

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

No branches or pull requests

7 participants