Skip to content

Add relativeUrls option for sprite URLs in library builds - #25

Open
NullVoxPopuli wants to merge 1 commit into
svg-jar:mainfrom
NullVoxPopuli:relative-sprite-urls
Open

NullVoxPopuli wants to merge 1 commit into
svg-jar:mainfrom
NullVoxPopuli:relative-sprite-urls

Conversation

@NullVoxPopuli

Copy link
Copy Markdown
Contributor

Adds a relativeUrls option.
With it, library builds point at their sprite relative to the chunk, so the consuming app serves it under the app's own base.

// before (base: '/')
createSvg('0 0 16 16', null, null, '/assets/sprite-656471e5.svg#6711e4a3');

// relativeUrls: true
createSvg('0 0 16 16', null, null, new URL('./assets/sprite-656471e5.svg', import.meta.url).href + '#6711e4a3');

Why

A library built with tsdown/Rolldown bakes base into its sprite URLs at build time.
It can't know the base of each app that consumes it.
An app served at /pr-previews/pr-1234/ or /__demo__/foo/ then requests /assets/sprite-<hash>.svg from the domain root, and the icons don't render.

With new URL(..., import.meta.url), the app's bundler does the work.
Vite rewrites the URL under its base in dev, and copies the sprite into the app's build with a hash.
The library no longer needs the app to serve dist/assets at a fixed path.

Notes

  • The default is false, so existing output is unchanged.
  • The relative path is computed from chunk.fileName, so chunks in subdirectories get ../assets/....
  • The #<id> fragment is appended after .href, so the bundler sees a plain file URL.
  • ?file imports and refs inside sprite sheets still use base.
    I kept them out of scope, and the option docs say so.

Testing

  • Rolldown integration tests: relative URL in a root chunk, ../ from a nested chunk, and the sprite is still emitted.
  • resolveOptions unit tests for the default.
  • Tried in a real monorepo, where a tsdown-built Ember addon is consumed by Vite 8 apps.
    The dev server serves the sprite under a non-root base.
    vite build emits one hashed sprite and writes <base>assets/sprite-<hash>-<vitehash>.svg into the code.

With relativeUrls, renderChunk writes each sprite reference as new URL('./assets/sprite-<hash>.svg', import.meta.url).href + '#<id>'.
The path is relative to the chunk that holds it.
The app that consumes the library then resolves the sprite with its own bundler, under its own base.
Without the option, output is unchanged.
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.

1 participant