vite: Loading SCSS with the `?url` flag causes the import to fail
- Read the docs.
- Make sure this is a Vite issue and not a framework-specific issue. For example, if it’s a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/vue-next instead.
- This is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
Describe the bug
Similar to #2455, when importing SCSS into a JS file, with the ?url
flag, the import will fail.
A related, but apparently different bug, is that if ?url
is used with a CSS file, it evaluates to a string like export default "/src/style.css"
. This may deserve a separate issue.
Reproduction
This can be reproduced with:
yarn create @vitejs/app --template vue vite-sample
; cdyarn add sass
- Create
src/style.scss
- Add an import to
App.vue
import data from "./style.scss?url" console.log(data)
Error in console
[plugin:vite:css] expected "{".
╷
1 │ export default "/src/style.scss"
│ ^
╵
src/style.scss 1:33 root stylesheet
/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/src/style.scss:1:33
at Object._newRenderError (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:13537:19)
at Object._wrapException (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:13374:16)
at _render_closure1.call$2 (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:80373:21)
at _RootZone.runBinary$3$3 (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:27269:18)
at _FutureListener.handleError$1 (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:25797:19)
at _Future__propagateToListeners_handleError.call$0 (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:26094:49)
at Object._Future__propagateToListeners (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:4543:77)
at _Future._completeError$2 (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:25927:9)
at _AsyncAwaitCompleter.completeError$2 (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:25270:12)
at Object._asyncRethrow (/home/jonathan/src/git.ec2software.com/jonathan/vite-sample/node_modules/sass/sass.dart.js:4292:17
Click outside or fix the code to dismiss.
You can also disable this overlay with hmr: { overlay: false } in vite.config.js.
System Info
vite
version: 2.1.0- Operating System: Arch Linux
- Node version: v15.10.0
- Package manager (npm/yarn/pnpm) and version: yarn
Logs (Optional if provided reproduction)
- Run
vite
orvite build
with the--debug
flag. - Provide the error log here.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 28
- Comments: 23 (4 by maintainers)
Currently queries has these behaviors.
import cssContent from 'foo.css'
: bundles files into a single css file and obtains the content of it (also loads style)import cssContent from 'foo.css?inline'
: bundles files into a single css file and obtains the content of itimport rawCssContent from 'foo.css?raw'
: raw css file (no bundle or transpile)import worker from 'foo.js?worker'
: bundles files into a single worker fileimport workerUrl from 'foo.js?worker&url'
: bundles multiple files into a single worker file and obtains the url of it (#7914)I think making it like below will have a consistency with the queries above.
import cssUrl from 'foo.css?url'
: bundles files into a single css file and obtains the url of itimport rawCssUrl from 'foo.css?raw&url'
: obtains the url of raw css file (no bundle or transpile)Also these (it’s a bit off-topic)
import jsUrl from 'foo.js?url'
: bundles files into a single js file and obtains the url of it (#6757)import jsUrl from 'foo.js?raw&url'
: obtains the url of raw js file (no bundle or transpile)My expectation would be to point the the resulting CSS after compilation, so I can have a
link
tag that I inject at runtime reference it, so in development it would be/src/style.scss
(which the vite dev server compiles on request) and in production it would bedist/assets/style.b4186631.css
or whatever is output.If I understand, the problem of what to do is that the styles are concatenated, scoped to the JS, but I’m trying to reference a style directly, so it may be part of one or more bundles that’s associated with various scripts, not a single CSS bundle for that SCSS entrypiont.
The usecase I’m trying to solve is scoping my CSS inside of a shadow DOM element. Another domain is including a script from my site to get a component. I want to omit adding the CSS until I manually add it to the shadow node.
I don’t care if
scss
file has its compiled css’s url, but I thinkcss
file should get its url.import cssUrl from 'someCssFile.css?url'
: syntax like this should be supported. We need a way to let vite help us organize our files but we use those files in our way, like add link element after component A mounted and remove that link after A is destroyed.however:
import compiledCssUrl from 'someScssFile.scss?url'
: this has different meaningsI think we should write it like:
It would be super useful if we could use something like:
import conditionalStylesUrl from 'conditionalStyles.scss?url'
Ideally this would allow retrieving of a path to the resulting compiled css file which could then be dynamically inserted as a stylesheet conditionally based on some application logic. I’d love to know if there is already a way to do this?
The same error happens when using
raw
for scss files (import text from './src/style.scss?raw'
)Same issue devs! Any updates on this?
Any progress yet? I am facing a similar scenario when dealing with shadowdom, need to get scss compilation result and inject a preload link into head
Same issue. My team needs to have fine control over the order/position at which css files are added to the DOM, hence we cannot rely on vite’s built-in css import handler and must manually create
<link rel="stylesheet" href="...">
. We need the capability to get the asset url from css files for this work.The only work around we can think of is renaming the
.css
as.txt
, import it as?raw
, and manually set the<style>
tag inner html. This breaks our caching though.My use case is when using CSS within a Web Component. So:
Import meta works fine, but I guess the stylesheet isn’t processed? Correct me if I’m wrong. I’m not using some plugin yet (e.g.: autoprefixer), so I can’t say for sure.
Same problem for me basically. We want to load different SCSS files for different pages and use React Helmet for that and would like to point to the URL of the file dynamically instead of having Vite appending the style automatically to the page.
We have the same problem coming from CRA. Our use case is to import dynamic theme scss from a third party package based on a user setting. The css files are too big and too many to preload all of them, so we want to load them on demand. In CRA we imported the scss as url and appended it to the html head. Now in Vite that seems impossible as ?url doesn’t transform the sass css in build/preview mode.
I hope this will be fixed by e.g. ?inline&url, but for now I want to share our workaround. We ended up using dynamic import(), like import(‘@/stylesheets/themes/theme.light.scss’). This automatically bundles the sass as a separate css file in the assets folder and automatically links it in the html head on demand. The problem with this approach though is that the css files are appended but never removed. So here comes the “hacky” part: after import you need to toggle the dynamically linked css by using the media attribute. In dev mode this needs to be done on the appended <style …> tag, and in production mode on the <link …> tag. Downside of this approach is that all imported theme css files are attached to the DOM forever, but I think browsers are smart enough to allocate resources accordingly.
Our stripped-down react code is as follows:
small world, @sep2, that is exactly what blocked my team too. We have to put tinymce skin css files into the public folder with a manual copying step during in build. If you adopt the same workaround, make sure you add a version prefix/suffix somewhere in the public file path for immutable caching, or your user might get stuck with that version forever.
What do you expect to get by appending
?url
to an SCSS file? Multiple CSS files are going to be concatenated into one file during build so it’s not a 1 to 1 mapping like static assets.