Skip to content

fix(deps): resolve subpath extensions for packages without exports field#863

Merged
sxzz merged 3 commits intomainfrom
fix/resolve-dep-subpath-extensions
Mar 25, 2026
Merged

fix(deps): resolve subpath extensions for packages without exports field#863
sxzz merged 3 commits intomainfrom
fix/resolve-dep-subpath-extensions

Conversation

@sxzz
Copy link
Copy Markdown
Member

@sxzz sxzz commented Mar 25, 2026

  • This PR contains AI-generated code, but I have carefully reviewed it myself. Otherwise, my PR may be closed.

Description

When a dependency has no exports field in its package.json, subpath imports like source-map-support/register need to be resolved to their actual file path (e.g. source-map-support/register.js) for valid ESM output.

Key changes in src/features/deps.ts:

  • Rename DepPluginDepsPlugin for consistency with the module name (deps.ts)
  • Resolve dependency IDs upfront via this.resolve() and pass the ResolvedId to externalStrategy, avoiding redundant resolution in skipNodeModulesBundle
  • Add resolveDepPath(): when a dependency subpath import (e.g. foo/bar) resolves to a package without an exports field, rewrite the import to include the file extension (e.g. foo/bar.js)
  • externalStrategy can now return [true, resolvedId] to indicate external with a rewritten import path
  • Extract parseDepPath() as a shared utility used by both parseBundledDep and resolveDepPath
  • When shouldExternal is not explicitly set but resolved exists, forward the resolved result with moduleSideEffects

Other changes:

  • Update imports in src/features/rolldown.ts and src/plugins.ts to use DepsPlugin
  • Remove unused @publint/pack dev dependency from package.json, pnpm-workspace.yaml, and tsdown.config.ts

Linked Issues

Closes #854

Additional context

The resolveDepPath function works by:

  1. Checking if the resolved module has a packageJsonPath (from Rolldown's resolver)
  2. Skipping if the import already has a file extension or has no subpath
  3. Reading the package's package.json to check for an exports field
  4. If no exports field exists, using the actual resolved file path to construct the correct import specifier with extension

When a dependency has no `exports` field in its package.json, subpath
imports like `source-map-support/register` need to be resolved to their
actual file path (e.g. `source-map-support/register.js`) for valid ESM output.

Refactors DepsPlugin (renamed from DepPlugin) to resolve dependency paths
upfront and return custom resolved IDs when the package lacks an exports field.
Also switches tsconfig to bundler module resolution and removes @publint/pack
dev dependency.
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 25, 2026

Deploy Preview for tsdown-main ready!

Name Link
🔨 Latest commit fc1bc20
🔍 Latest deploy log https://app.netlify.com/projects/tsdown-main/deploys/69c3a7b55192140008b03da4
😎 Deploy Preview https://deploy-preview-863--tsdown-main.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 25, 2026

Open in StackBlitz

tsdown

pnpm add https://pkg.pr.new/tsdown@863 -D
npm i https://pkg.pr.new/tsdown@863 -D
yarn add https://pkg.pr.new/tsdown@863.tgz -D

create-tsdown

pnpm add https://pkg.pr.new/create-tsdown@863 -D
npm i https://pkg.pr.new/create-tsdown@863 -D
yarn add https://pkg.pr.new/create-tsdown@863.tgz -D

@tsdown/css

pnpm add https://pkg.pr.new/@tsdown/css@863 -D
npm i https://pkg.pr.new/@tsdown/css@863 -D
yarn add https://pkg.pr.new/@tsdown/css@863.tgz -D

@tsdown/exe

pnpm add https://pkg.pr.new/@tsdown/exe@863 -D
npm i https://pkg.pr.new/@tsdown/exe@863 -D
yarn add https://pkg.pr.new/@tsdown/exe@863.tgz -D

tsdown-migrate

pnpm add https://pkg.pr.new/tsdown-migrate@863 -D
npm i https://pkg.pr.new/tsdown-migrate@863 -D
yarn add https://pkg.pr.new/tsdown-migrate@863.tgz -D

commit: 10c21de

@sxzz sxzz merged commit c51502b into main Mar 25, 2026
13 of 14 checks passed
@sxzz sxzz deleted the fix/resolve-dep-subpath-extensions branch March 25, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relative imports from a package should also receive file extension when format is esm

1 participant