vite: manifest.json does not include assets
Describe the bug
Statically imported assets (SVG file in my case) will get bundled and created in the outDir
, but are missing in the generated manifest.json
.
vite.config.js
import { defineConfig } from 'vite';
import legacy from '@vitejs/plugin-legacy';
export default defineConfig({
base: '/static/',
publicDir: 'assets/static/',
build: {
manifest: true,
outDir: 'public/static/',
assetsInlineLimit: 0,
rollupOptions: {
input: 'assets/main.ts',
},
},
plugins: [legacy()],
});
assets/main.ts
import './icon.svg';
manifest.json
{
"assets/main-legacy.ts": {
"file": "assets/main-legacy.dd90b2c6.js",
"src": "assets/main-legacy.ts",
"isEntry": true
},
"assets/main.ts": {
"file": "assets/main.9470b65c.js",
"src": "assets/main.ts",
"isEntry": true
}
}
output files
- main.9470b65c.js
- main-legacy.dd90b2c6.js
- icon.a0d73e22.svg
System Info
vite
version:2.0.5
- Operating System:
Windows 10
- Node version:
12.16.1
- Package manager (npm/yarn/pnpm) and version:
npm 7.5.3
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 3
- Comments: 20 (6 by maintainers)
Had a look and Vite is already tracking and outputting any assets regardless of their usage so I think it makes sense to expose them in the manifest so those integrating with a backend can take advantage of Vite for processing assets not directly used by Vite.
In my testing importing static assets via
import.meta.glob
is enough for Vite to process them even if not referenced.vite.config.js
src/main.ts
src/main.scss
With the above Vite will process and output files matching the glob
./files/**/*
. The only missing bit is a way to get the final path. Looking atgenerateBundle
the asset chunks are present but not exposed so I propose we add a_assets
entry within the manifest that contains all assets Vite has processed e.g.The
_assets
entry contains assets both used within chunks i.e. fonts and non used assets i.e. those imported via the glob. This is desirable as it then allows you to more easily reference files like fonts for things like generating preload directives and other assets such as favicons or static assets referenced in the frameworks templating language.I’ve quickly modified
vite/packages/vite/src/node/plugins/manifest.ts
to achieve the above but I’m likely missing something.The only thing that isn’t quite right is how css is handled as Vite considers it an asset but the full path is stripped by the time the manifest is generated i.e. instead of
src/main.scss
it appears asmain.css
.I’m not sure if we should remove the CSS properties or try to add the full path back in. If we did it keep it and use the source path it would then be possible to use css as an entry.
This is currently possible (not sure if intentional) but you’d have to remember to reference your css by the file name (
entry.scss
) rather than path (src/entry.scss
) and I’m assuming that relying on filename only will result in conflicts.But by keeping the original path things would work as expected.
To summarise there are two things to look at:
_assets
I feel like a “web bundle manifest” specification/standard would be really helpful. As some already mentioned, I would also assume all files, which end up in the final bundle/dist/build directory, to be present in the manifest.
It seems that with the latest
vite@2.3.x
version, even without thelegacy
plugin, the issue now pops up. Statically imported images will be copied to theoutDir
folder, but do not show up in the generatedmanifest.json
file.I realize that this behavior is probably something which is not needed in modern, JS-based (PWA) applications, but in our case, when using
vite
in a more classic backend-rendered (PHP) application, not having all imported assets in themanifest.json
file, results in not being able to render/access those assets in the first place.Is there any chance it would be considered for
vite
to list all imported assets inmanifest.json
for this reason? Thanks a lot!No, I checked both manifest files, and neither includes required assets unless imported AND used in a JS file. Further, the keys are wrong in that case, as the keys are literally “…/images/something” which is not consistent with they way it worked with webpacker. All of these JS bundlers are so configuration heavy. They say they work, but not for images, not for SVGs, not for Vue components… Isn’t there one that actually works as a drop-in replacement for webpacker and isn’t so brittle? (The whole reason for switching away from webpacker/webpack is because it’s always breaking things and not intuitive, but then if all the alternatives are just as troublesome to figure out, and the docs are just as bad, what is the incentive to switch?)
I have encounter same question. use
build.cssCodeSplit: false
would misscss
in themanifest.json
Also seeing this, and like @thasmo we’re using Vite in a hybrid approach where once built a PHP back-end takes over. The files are indeed copied to the
dist
directory (in our case, we want to run them throughimagemin
), but are missing from the manifest.vite.config.js
src/main.js
manifest.json
That’s despite the actual
dist
folder containing the asset.I’ve gone all the way back to Vite v2.0.0 and this has never worked it seems?
The only way I have got this to work is if I actively use the asset somehow. For instance, doing:
Will add it to the manifest exactly as I expect. Not sure if this is a bug, or expected behaviour?
Fixed in #6649
If I had to guess, imports are probably promises that are lazily resolved. So it isn’t until an import is actually used (thus the behavior that @engram-design is seeing) that it’d be added to any manifest, just as a resource that can’t be resolved (404 for example) isn’t added either.
So I’m guessing this probably is a feature, not a bug, in that unused resources (unresolved promises) are not included in the production build.
The behavioral expectation likely comes from experience with task runners, rather than loaders.
It seems this happens when using the
legacy
plugin. Removing thelegacy
plugin resolves the issue. In addition, I noticed when settingbuild.cssCodeSplit: false
CSS files won’t be generated/created if thelegacy
plugin is used. On top of that, if thelegacy
plugin is disabled andbuild.cssCodeSplit: false
is still set, the CSS files will be generated, but are still missing in themanifest.json
.@Shinigami92 This behavior is intentional, at least at the time of this comment: https://github.com/vitejs/vite/pull/1774#issuecomment-769447478
What threw me was the fact that it was processing the file - moving it to
dist
but not adding it to the manifest. If the file is deemed not required, should it even end up indist
?I’ll say that in my case, I mention the use of
imagemin
. As @khalwat rightly guessed, I’m coming from Webpack (Laravel Mix) where I would have as part of my production build process, a task that scans thesrc/img/**/*
folder for any and all images, processes them, and copies them todist/img
.I’m trying to replicate that by using vite-plugin-imagemin which works perfectly, but only for assets used in Vue components, or CSS files. There are cases I want to use these assets in Twig templates, outside of Vite’s awareness. Hence, my journey to try and “add” every asset to the manifest.
But I’ve pivoted back to my original goal, and forked the
vite-plugin-imagemin
plugin to allow direct copying fromsrc/img
todist/img
. In my Twig templates, I can now refer to these specifically via/dist/img/my-image.png
upon build. During development these are resolved to use the dev server,http://localhost:3000/img/my-image.png
.It’s quite likely me scenario is different, but just thought I’d chime in - just in case anyone has a similar scenario and how to approach this. My approach using Craft CMS for the project involves Twig server-side code, but also a sprinkling of Vue, so it’s very much a hybrid approach, similar to a lot of people in the Laravel community.
@Shinigami92 Would you be okay with removing the
plugin: legacy
tag as I think the issue now also occurs without it? Thanks!