Turbopack: Add support for specifying additional roots - #98003
Conversation
… config - The Next config is parsed inside a turbo-tasks function, which is too late, pass it in as separate NAPI object as part of the project options. - Improve error handling and formatting of AdditionalRootIssue
- AdditionalRootConfig::canonicalize returns a Result instead of an Option - The handling of 'optional' moves out of `AdditionalRootConfig::canonizalize` and into the callsite - If something doesn't implement Issue call it Error instead. - Rename AdditionalRootConfigIsssue to AdditionalRootIssue - Don't flatten AdditionalRootError into AdditionalRootIssue
…rust at all, the js callers already do this for us
…starting the process
…lean up constructor, add nicer DiskFileSystemMap::empty API
…ject_container_state implementation
Failing test suitesCommit: 276c31f | About building and testing Next.js
Expand output● filesystem-caching with cache disabled › should cache or not cache loaders ● filesystem-caching with cache disabled › should cache or not cache loaders ● filesystem-caching with cache disabled › should cache or not cache loaders ● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change) ● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change) ● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change) ● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page) ● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page) ● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page) ● filesystem-caching with cache disabled › should allow to change files while stopped (next config change) ● filesystem-caching with cache disabled › should allow to change files while stopped (next config change) ● filesystem-caching with cache disabled › should allow to change files while stopped (next config change) ● filesystem-caching with cache disabled › should allow to change files while stopped (env var change) ● filesystem-caching with cache disabled › should allow to change files while stopped (env var change) ... truncated ...
Expand output● output: standalone with twoslash › should annotate twoslash types esnext
Expand output● app-dir action handling › HMR › should support updating the action
Expand output● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist ● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist ● Test suite failed to run
Expand output● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist ● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist ● Test suite failed to run
Expand output● filesystem-caching with cache disabled › should cache or not cache loaders ● filesystem-caching with cache disabled › should cache or not cache loaders ● filesystem-caching with cache disabled › should cache or not cache loaders ● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change) ● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change) ● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change) ● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change) ● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page) ● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page) ● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page) ● filesystem-caching with cache disabled › should allow to change files while stopped (next config change) ● filesystem-caching with cache disabled › should allow to change files while stopped (next config change) ● filesystem-caching with cache disabled › should allow to change files while stopped (next config change) ● filesystem-caching with cache disabled › should allow to change files while stopped (env var change) ● filesystem-caching with cache disabled › should allow to change files while stopped (env var change) ... truncated ...
Expand output● output: standalone with twoslash › should annotate twoslash types esnext Other failing CI jobs |
| bail!("Cannot read directory as file content: {target_fs_path}") | ||
| } | ||
| _ => bail!("Invalid cross-filesystem symlink target"), |
There was a problem hiding this comment.
Probably don't want to bail here
| async fn canonicalize_untracked(sys_path: RcStr) -> Vc<OptionRcStr> { | ||
| Vc::cell( | ||
| retry_blocking(|| canonicalize_to_rcstr(Path::new(&*sys_path))) | ||
| .await | ||
| .ok(), | ||
| ) | ||
| } | ||
|
|
||
| let ancestors: SmallVec<[&Path; 8]> = target_sys_path.ancestors().collect(); | ||
| for prefix in ancestors.into_iter().rev().skip(1) { | ||
| let Some(prefix_str) = prefix.to_str() else { | ||
| return Ok(None); | ||
| }; | ||
| let Some(canonical) = canonicalize_untracked(RcStr::from(prefix_str)) | ||
| .owned() | ||
| .await? |
There was a problem hiding this comment.
Add some comments about how this is similar to resolve_link_target_ancestry_slow_path, or figure out a better way to share code between these two places.
Possible future follow-up PR: I'd also like to just optimize this pattern a bit better, but it'll involve hacking around turbo-tasks in some unsafe ways.
Full motivation and plan here: https://app.notion.com/p/vercel/Turbopack-pnpm-Global-Virtual-Store-383e06b059c480579403ddfd71cc2d40?source=copy_link
The goal is to allow
DiskFileSystemto traverse outside of it's own root to other configuredDiskFileSystems when following symlinks. We may allow traversal in other situations in the future, but this is limited to symlink resolution for now.Global Virtual Store
The motivation for this is to enable pnpm's Global Virtual Store feature (and there are other package managers doing this, including nub and bun).
We'd expose the ability to manually configure this in
next.config.js, but we should also auto-configure ourselves for popular package managers (or at least make a best effort to do so, thePNPM_HOMEsemantics can be complicated). TheignoreIfMissingoption is provided for this situation: We can configure a bunch of roots automatically, and they only actually get set up if they exist, the check for directory existence is cheap.Open questions
Issuerequires a file path. Arguably the right file path here is thenext.config.jsfile, though right now we're using the project root. If we lifted the path requirement fromIssue, we could construct the error earlier.DiskFileSystemis constructed.additionalRootsconfig is not experimental. Should it be experimental?Statefor mutating theDiskFileSystemMapstored onDiskFileSystemInner. Is there any better way we should be doing this?Vc<DiskFileSystemMap>themselves.