Emitting assets in library mode #13172
Replies: 2 comments
-
@jonaskuske we've moved this RFC to the vitejs/vite repo. We're going to make the vitejs/rfcs repo private for the moment until there is a bigger need for a separate space. In the end, we continued using feature requests and discussions here. |
Beta Was this translation helpful? Give feedback.
-
I have a monorepository with several UI libraries in react used by applications outside this monorepository. While a solution does not unfold, what would be the simplest workaround for a use case where I use images, fonts and videos from within the same library? I thought about leaving the files in the public folder, and in the application, changing the path of the public folder to node_modules/@my-org/my-lib/assets, but then I would need to create another assets folder inside public, otherwise when building the library each folder inside public will go to the root of the outDir, and the vite public folder configuration parameter only accepts a single string and that would prevent the application from adding more files. I remember reading somewhere that maybe using an exclusive package for these assets might work, but I don't understand how. |
Beta Was this translation helpful? Give feedback.
-
Vite currently inlines all assets if a project is built in library mode – from my understanding, that's because the JS of a library might be loaded from arbitrary base URLs by downstream consumers or bundled with their other code, so just using a base path like
/
or./
to reference emitted assets will not work. But inlining everything is far from ideal, as it leads to multiple-MB file sizes for the generated JS and CSS files, prevents lazy-loading of workers or JS chunks and thus caused quite a few issues and PRs:build.lib
is set #7656There's a proposal to enable emitted (instead of inlined) assets if a library is built in
es
mode, as in that case the full URL to the runtime directory can be read fromimport.meta.url
. This proposal was accepted roughly a year ago but isn't implemented yet and I'm not sure if it's still consensus and on the roadmap: #4454 (comment)I'd like to extend that proposal to allow emitting assets no matter the format if an (absolute?)
base
is specified. This allows usage of library mode in cases where the deploy URL is known ahead of time, for example if the library is not meant for public distribution but for a controlled runtime environment or if building something like a WordPress or Kirby CMS plugin. (in the case of Kirby, plugin files are always reachable through/media/plugins/<author>/<pluginName>/assets/...
no matter the location on the file system)It'd also allow usage like
base: "__RUNTIME_BASE_URL__/assets/"
, which can then be string-replaced by the server at runtime.Another aspect to this is that afaik the main problem only exists for assets referenced from JS:
assets referenced in CSS via (relative)
url()
are resolved from the stylesheet location, so usage likeurl(./fonts/papyrus.woff2)
will work no matter the deploy location as long as the internal directory structure of the library itself stays intact.There are quite a few questions to investigate and consider:
How can we support asset resolving in a way that's compatible with the various consumption options?
Is leaving the imports as-is for downstream bundler consumption an option?
As proposed in feat(vite): emitAssetsWithModule in library mode #9734
Should we consider to treat assets referenced from JS and CSS differently?
Assets imported from JS could continue to be inlined, but be emitted when loaded from CSS (fonts!), where relative references should work without issue (at least at runtime, the behavior of popular bundlers needs to be investigated)
What's a good API design to support the different ways of loading assets?
Could include:
import.meta.url
(ordocument.currentScript
, see next?)One design I have in mind would be to:
build.lib.emitAssets
true
, load assets frombase
if it is set, otherwise fromimport.meta.url
if the format ises
es
and there's nobase
, warn or erroremitAssets: 'css'
, enabling CSS assets like fonts, bg images or icon spritesheets to be emitted independent frombase
orformat
configurationIs it possible to support relative references in non-ES builds through
document.currentScript
?Not sure if that works, but
import.meta.url
could potentially be substituted withdocument.currentScript
to allow relative./
references in non-ES libraries. Would prevent SSR usage, but that's an acceptable trade-off in some scenarios (e.g. private libs that are client-only, WordPress scripts, ..)Wanted to start this general discussion here – if interest is there, I'd be happy to dive deeper and play around with API design and the technical feasibility of the various options :)
Beta Was this translation helpful? Give feedback.
All reactions