Vite treats styles and assets as part of the module graph, which changes how you reference them.
In Vite, CSS and assets are imported from JavaScript, and the build takes care of the rest.
CSS:
import "./style.css"injects the styles (with HMR in dev) and extracts them into a hashed.cssfile in production.- Files named
*.module.cssare CSS modules:import styles from "./card.module.css"gives an object of locally scoped class names. - Sass, Less and Stylus work after installing the preprocessor (
npm i -D sass-embedded). PostCSS config is picked up automatically, and Lightning CSS handles minification and syntax lowering.
Assets:
import logoUrl from "./logo.svg"returns a URL string. Small assets (under 4 KB by default,build.assetsInlineLimit) are inlined as data URIs; larger ones get hashed filenames likelogo-Bx3k9.svg.- Query suffixes change what you get:
?url(always a URL),?raw(file contents as a string),?inline(data URI),?worker(a Web Worker constructor). new URL("./img.png", import.meta.url)also works for dynamic asset paths, as long as the path is statically analyzable.import data from "./data.json"works too, including named imports of top-level fields.
Referencing assets in CSS (url(./bg.png)) and in index.html is rewritten the same way.
Example
import "./style.css"; // global styles
import styles from "./card.module.css"; // { card: "_card_1x2y3" }
import logoUrl from "./logo.svg"; // "/assets/logo-Bx3k9.svg" (or a data: URI if tiny)
import notes from "./notes.txt?raw"; // file contents as a string
import Worker from "./crunch.js?worker"; // Web Worker constructor
import { version } from "../package.json"; // named import from JSON
const card = document.createElement("div");
card.className = styles.card;
card.innerHTML = `<img src="${logoUrl}" alt=""> v${version}<pre>${notes}</pre>`;
document.body.append(card);
const worker = new Worker();
worker.postMessage({ n: 40 });Remember
- Import CSS from JS;
*.module.cssgives scoped class names - Imported assets become hashed URLs or inline data URIs
- Suffixes: ?url, ?raw, ?inline, ?worker
- Preprocessors work once installed, no config needed
Watch out for
- Building asset paths with string concatenation at runtime, which the bundler cannot see or hash.