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

feat: support a vite entry point (export condition / main field) #15643

Closed
wants to merge 13 commits into from

Conversation

milesj
Copy link

@milesj milesj commented Jan 18, 2024

Description

After speaking with @yyx990803, we're looking for a way to better support local packages (via monorepo/workspaces) without a build step. The current suggestion is to set resolve.aliases, but what if we leaned on the package ecosystem more?

This PR adds support for a vite condition for package exports, and a vite main field (when not using exports). Both patterns can point to a source file, instead of a built file. These vite entry points will only be resolved for local packages, and not packages found in node_modules.

Furthermore, for backwards compatibility, I wrapped this in a vitePackageEntryPoints experiment for now.

For more information, look at the docs in this PR.

Additional context


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines, especially the Pull Request Guidelines.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Update the corresponding documentation if needed.
  • Ideally, include relevant tests that fail without this PR but pass with it.

Copy link

stackblitz bot commented Jan 18, 2024

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@milesj milesj changed the title new: Support a vite entry point (export condition / main field) feat: Support a vite entry point (export condition / main field) Jan 18, 2024
@@ -0,0 +1,10 @@
import { expect, test } from 'vitest'
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This playground tests normal resolve.alias usage.

@@ -0,0 +1,38 @@
import { describe, expect, test } from 'vitest'
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This playground tests main/exports vite usage. There's many different patterns.

@milesj milesj changed the title feat: Support a vite entry point (export condition / main field) feat: support a vite entry point (export condition / main field) Jan 19, 2024
@bluwy
Copy link
Member

bluwy commented Jan 22, 2024

I'm not a fan of introducing Vite-specific metadata to the package.json. Even if it's local-only, the fields are also likely to be published and would be exposed and even point to a non-existing source file?

I think publishConfig could be used instead for this case: pnpm docs and npm docs. You can then split out your dev and publish-only fields this way.

@dominikg
Copy link
Contributor

dominikg commented Jan 22, 2024

so the vite condition would only be used during development? wouldn't it be easier to use the existing development condition then? https://nodejs.org/api/packages.html#community-conditions-definitions

I agree with @bluwy that we should not add a new top-level field to package.json. This feature will only be used by new projects/adopted, so if it is only supported via exports maps that should be fine. Resolving via top level package.json fields is basically a legacy option today, no need to add new fields to it.

@milesj
Copy link
Author

milesj commented Jan 22, 2024

@bluwy Interesting suggestion, but I don't see how publishConfig would work for something that is local/dev only. I'd also argue that export conditions are the preferred way to support tool-specific logic. It's exactly why custom conditions are allowed.

@dominikg The development condition kind of assumes a JS file that can be evaluated at runtime. Throwing in TS files, or .vue files (maybe), or something else, kind of breaks that guarantee. It also just exists for NODE_ENV checks.

I'm cool with removing the top-level vite but the exports condition is still viable. Maybe source or bundler for the export condition, instead of vite? That way it's generic, and can be used by other tools.

@bluwy
Copy link
Member

bluwy commented Jan 23, 2024

@bluwy Interesting suggestion, but I don't see how publishConfig would work for something that is local/dev only. I'd also argue that export conditions are the preferred way to support tool-specific logic. It's exactly why custom conditions are allowed.

You can configure it like this:

{
  "name": "lib",
  "main": "./src/index.js",
  "publishConfig": {
    "main": "./dist/index.js"
  }
}

Conditions are indeed the more reliable way to declare them, but I don't think it's best for a tool that pushes towards standards. Encouraging the vite condition feels like the start of introducing proprietary APIs in libraries that we had always refrained from.

@dominikg
Copy link
Contributor

Also not keen about adding on to the pile of custom conditions. The landscape there is messy already and instead of adding more ways we should focus on enabling projects to migrate towards clean esm and providing tooling on top of existing conditions to make it work.

case in point: Webpack made the "module" condition a thing https://webpack.js.org/guides/package-exports/#conditions and appearantly wmr also made "esmodules". ugh.

All this does is creating more fragmentation some sort of lock-in mechanism where either all bundlers are forced to support each others inventions or projects will be tied to the one they started on forever.

If you are using exports conditions, regardless of vite or an existing one, you would have to ship the referenced files in published packages too, as you have no control over the conditions used on the consumers side. So for public packages i think publishConfig is the way to go. For local only packages i think the development or production condition can work.

@patak-dev patak-dev added the p3-significant High priority enhancement (priority) label Jan 24, 2024
@milesj
Copy link
Author

milesj commented Jan 25, 2024

@yyx990803 @bluwy @dominikg

Took a step back to reimplement this. I agree, exports adds a lot of weird overhead. It's also a lot for consumers to configure, so I thought, why can't we just automate this?

And that's exactly what I did. With my previous attempt, we were able to determine which packages are local or not. So I expanded this to automatically resolve source files of local packages, with no configuration from the consumer! This actually worked really well in the playground.

Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this from a different perspective. Besides my comments/concerns below, additionally I think from our last meeting, we should only need improved documentation on setting up monorepos in Vite.

I don't think there's something Vite can do internally or automatically to make it just work without injecting Vite-specific APIs or heuristics, which we want to avoid. So I think it's best we only do the documentation part, which is also tracked at #10447

Comment on lines +1143 to +1151
// We need to support array conditions like `["./*.js", "./*.mjs"]`
// So loop through each result and find one that actually exists
if (result.length > 1) {
for (const entry of result) {
if (fs.existsSync(path.join(pkg.dir, entry))) {
return entry
}
}
}
Copy link
Member

@bluwy bluwy Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently intentionally don't support this as it's not following the spec. Node.js only specifies to use the next element if the specifier is invalid, not if it don't exist on the fs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know, I can remove it.

// We do this check here, so that it only runs once per package,
// and not for every file in the package!
if (inWorkspace) {
for (const srcName of ['src', 'sources']) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Vite should be hardcoding these directories. The users should be free to arrange the output however they want.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I originally started adding this behind a config setting, similar to file extensions, but pushed it off to get the POC working.

@milesj
Copy link
Author

milesj commented Jan 25, 2024

Let's wait and see what Evan's thoughts on this are. I was tasked in finding a way to make monorepo setups "just work" without extra configuration (this includes alias mapping). I think for the majority of consumers, the automatic sources will work just fine. For others, they can just disable it, something like:

resolve: {
  localSources: false
}

We could even expand the config and give consumers more control. But I feel like this is getting away from the original goal.

resolve: {
  localSources: ['package-a', 'package-b'],
  srcDirs: ['lib', 'app'],
}

@bluwy
Copy link
Member

bluwy commented May 9, 2024

Closing this as the Vite team had discussed with Evan and this isn't the way we want to go for now.

@bluwy bluwy closed this May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p3-significant High priority enhancement (priority)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants