Closed thasmo closed 2 years ago
It seems this happens when using the legacy
plugin. Removing the legacy
plugin resolves the issue. In addition, I noticed when setting build.cssCodeSplit: false
CSS files won't be generated/created if the legacy
plugin is used. On top of that, if the legacy
plugin is disabled and build.cssCodeSplit: false
is still set, the CSS files will be generated, but are still missing in the manifest.json
.
repro repo: https://github.com/thasmo/vite-2375
Anything else I can provide? Thank you!
I have encounter same question.
use build.cssCodeSplit: false
would miss css
in the manifest.json
It seems that with the latest vite@2.3.x
version, even without the legacy
plugin, the issue now pops up. Statically imported images will be copied to the outDir
folder, but do not show up in the generated manifest.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 the manifest.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 in manifest.json
for this reason? Thanks a lot!
@Shinigami92 Would you be okay with removing the plugin: legacy
tag as I think the issue now also occurs without it? Thanks!
Am also seeing this behavior (Vite 2.4.3). With a plain vanilla create-vite
repo with zero plugins, I imported CSS, JS, font, and image files. All were generated with hashed file names, but only the CSS and JS files were mentioned in manifest.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 through imagemin
), but are missing from the manifest.
vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
build: {
manifest: true,
},
})
src/main.js
import './icon.svg';
manifest.json
{
"index.html": {
"file": "assets/index.aa78867d.js",
"src": "index.html",
"isEntry": true
}
}
That's despite the actual dist
folder containing the asset.
assets/index.aa78867d.js
assets/icon.03d6d6da.svg
index.html
manifest.json
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:
import icon from './icon.svg';
console.log(icon)
Will add it to the manifest exactly as I expect. Not sure if this is a bug, or expected behaviour?
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.
@engram-design That gets me over the hump in handling this for other types of assets. Much obliged! And thanks, also, to @khalwat for the educated guess, which suggests we shouldn’t wait for a fix if, indeed, it’s intentional rather than a bug.
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 in dist
?
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 the src/img/**/*
folder for any and all images, processes them, and copies them to dist/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 from src/img
to dist/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.
@engram-design Yes. Now I have to get my CSS’s @font-face
to point to the hashed font file. I see there’s postcss-url so I’m now looking into that.
Edit: Looks like that ain’t gonna cut it. 😄 Still looking.
Edit 2: The reason I’m trying to figure out this latest item is because Vite isn’t converting my @font-face
src: url()
to the necessary URL, although the docs say this is automatic. Here's my current vite.config.js
, which — like most of my repo’s Vite-related config — is borrowed heavily from the eleventy-with-vite
repo:
import { defineConfig } from "vite";
import legacy from "@vitejs/plugin-legacy";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [legacy()],
build: {
outDir: "_site",
assetsDir: "assets-vite", // default = "assets"
// Sourcemaps are nice, but not critical for this to work
sourcemap: true,
manifest: true,
rollupOptions: {
input: "/src/client/main.js",
},
},
css: {
postcss: {
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
require('postcss-nesting'),
require('postcss-csso'),
],
}
}
})
Edit 3: Also, my entry file:
import "vite/dynamic-import-polyfill"
import "../assets/js/lazyload.min.js"
import "../assets/js/lazyload-helper.js"
import "../assets/js/mobile-menu-helper.js"
import font from "../assets/fonts/Inter-VF_subset.woff2"
console.log(font) // see https://github.com/vitejs/vite/issues/2375
import "../assets/css/index.css"
Edit 4: Trying a similar import
on a bare-bones Vite (not Eleventy/Vite) repo, the @font-face
url()
does get the proper treatment, so this would appear not to be a Vite limitation.
@Shinigami92 This behavior is intentional, at least at the time of this comment: https://github.com/vitejs/vite/pull/1774#issuecomment-769447478
@Shinigami92 This behavior is intentional, at least at the time of this comment: https://github.com/vitejs/vite/pull/1774#issuecomment-769447478
Thanks for the info
Should I close this issue then and mark as wont fix
?
If it is intentional to exclude assets from the manifest(s),
@tgrushka Vite Ruby does not mention it because it generates its own manifest-assets.json
to cover for this missing feature in Vite.js.
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?)
This thread is about Vite.js, please open a Discussion in Vite Ruby if you need help migrating from Webpacker.
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.
src
├── entry.scss
├── files
│ └── favicon.svg
├── fonts
│ ├── my-font.woff
│ └── my-font.woff2
├── main.scss
└── main.ts
vite.config.js
export default defineConfig({
build: {
rollupOptions: {
input: 'src/main.ts'
}
}
})
src/main.ts
import './main.scss'
let files = import.meta.glob('./files/**/*');
// The "files" variable doesn't need to used for imports to get processed.
src/main.scss
@font-face {
font-family: "Font";
font-style: normal;
font-weight: 400;
src:
url("/src/fonts/my-font.woff2") format("woff2"),
url("/src/fonts/my-font.woff") format("woff");
}
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 at generateBundle
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.
{
"_assets": {
"src/files/favicon.svg": "assets/favicon.17e50649.svg",
"src/fonts/my-font.woff2": "assets/my-font.bf47658a.woff2",
"src/fonts/my-font.woff": "assets/my-font.80d4cac9.woff",
"main.css": "assets/main.eac10a5f.css"
},
"src/main.ts": {
"file": "assets/main.6097d7e4.js",
"src": "src/main.ts",
"isEntry": true,
"css": [
"assets/main.eac10a5f.css"
],
"assets": [
"assets/my-font.bf47658a.woff2",
"assets/my-font.80d4cac9.woff"
]
}
}
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.
if (chunk.type === 'asset') {
if (!manifest['_assets']) {
manifest['_assets'] = {}
}
let name = normalizePath(
path.relative(config.root, chunk.name)
)
manifest['_assets'][name] = chunk.fileName
}
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 as main.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.
export default defineConfig({
build: {
rollupOptions: {
input: [
'src/main.ts',
'src/entry.scss',
]
}
}
})
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.
<link rel="stylesheet" href="/assets/{{ manifest['_assets']['entry.css'] }}" />
But by keeping the original path things would work as expected.
{
"_assets": {
"src/files/favicon.svg": "assets/favicon.17e50649.svg",
"src/fonts/my-font.woff2": "assets/my-font.bf47658a.woff2",
"src/fonts/my-font.woff": "assets/my-font.80d4cac9.woff",
"src/main.scss": "assets/main.eac10a5f.css",
"src/entry.scss": "assets/entry.wef646xf.css"
},
"src/main.ts": {
"file": "assets/main.6097d7e4.js",
"src": "src/main.ts",
"isEntry": true,
"css": [
"assets/main.eac10a5f.css"
],
"assets": [
"assets/my-font.bf47658a.woff2",
"assets/my-font.80d4cac9.woff"
]
}
}
<link rel="stylesheet" href="/assets/{{ manifest['_assets']['src/entry.scss'] }}" />
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.
Fixed in #6649
Describe the bug
Statically imported assets (SVG file in my case) will get bundled and created in the
outDir
, but are missing in the generatedmanifest.json
.vite.config.js
assets/main.ts
manifest.json
output files
System Info
vite
version:2.0.5
Windows 10
12.16.1
npm 7.5.3