Home > OS >  Vite recognizes link with sass on npm run build, but not on npm run dev
Vite recognizes link with sass on npm run build, but not on npm run dev

Time:05-12

I am using a <link> tag to import a SASS/SCSS in the Vite/VueJS 3 index file:

<link rel="stylesheet" type="sass" href="/src/assets/test.scss">

The thing is it works very well when I run npm run build: the SCSS is converted into CSS, merged in the generated files and applied to the page as expected.

But when I run npm run dev, if I look at the page source code it simply outputted that <link ...> tag as-is to the browser.

This is my entire index.html file:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite</title>
    <link rel="stylesheet" type="sass" href="/src/assets/test.scss">
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

I tested more than one SCSS and it is not due to error in that file. For the sake of simplicity, this is a very small sample of valid SCSS test.scss that should affect the entire page:

body{
    background-color: red !important;
}

Why does it work on build, but does not work in dev (HRM)?

CodePudding user response:

After some trial and error, it seems that the link element is not correctly compiled by the dev (HRM) mode, even if production build works.

It may be realted to Webpack, as a more traditional way works for both, dev and build.

The solution is to create a script of "module" type and import the file there:

<script type="module">
  import "/src/assets/test.scss";
</script>

Now it gets compiled in both versions.

It works even with a shorter version of the same process:

<script type="module" src="/src/assets/bootstrap/scss/bootstrap.scss"></script>

Though the question "Why does it work on build, but does not work in dev (HRM)?" remains unanswered here.

CodePudding user response:

The type attribute of a <link> should not be conflated with the type attribute of a Vue SFC's <style> tag.

They are not the same thing.

<link>'s type attribute

Link is an HTMLElement and it's type attribute has to be a valid MIME type (e.g: text/html, text/css, application/atom xml, etc...). If it's not, the value is invalid and it's up to the browser to decide if/how it loads it and if/how it interprets it.

SFC <style>'s type attribute

In a single file component, Vue accepts one or more <style> tags. However, they are not actual HTML <style> tags. They are only named like that by the Vue team for convenience and because they serve the same purpose as an HTML <style> tag. After being processed, they actually output real HTML <style> tags, but they don't keep their type.

The SFC <style> tags are a Vue convention. Under the hood, Vue compiles their code and, where necessary, based on the type attribute, runs it through the correct CSS pre-processor, and, where necessary, based on the scoped or module attribute, alters the selectors so that the style only applies to that particular component. Finally, when the CSS has been processed, Vue creates an actual HTML <style /> tag and populates it with the result of the pre-processing in the form of valid CSS code (which the browser understands natively).

Regardless of what type you specify on an SFC <style> tag, the type attribute will be stripped.

In conclusion, don't place type="sass|scss|less" on a <link /> tag. If you do that, it's up to the browser to interpret its contents and, in most cases, it won't interpret it as per your expectation.


To make sure your stylesheet will be parsed by Vue, and get processed by the appropriate pre-processor, you could:

  • place a <style type="scss" src="path-to-file.scss" /> in any SFC
  • use import 'path-to-file.scss' directly in main.(js|ts)
  • use <script type="module" src="path-to-file.scss"/> (this is actually an alternative syntax for the import command above.

The above methods work for any type of pre-processor, as long as you add the proper loaders and packages to Vue (scss, less, etc...).

  • Related