8

I'm trying to export the following SASS variables into Javascript within my Vue project.

_export.sass

:export
    colorvariable: blue
    othercolorvariable: red

I'm following the response in this post as a template. However when I try to import my sass file below...

About.vue

<script>
import styles from "@/styles/_export.sass";

export default {
    name: "About",
    data() {
        return { styles };
    }
};
</script>

I receive the following error:

WAIT  Compiling...                                                                                                 2:17:03 AM

98% after emitting CopyPlugin

 ERROR  Failed to compile with 1 errors                                                                             2:17:03 AM

 error  in ./src/styles/_export.sass

Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Invalid CSS after '...les/main.sass";': expected 1 selector or at-rule, was "export: {"
        on line 1 of /Users/MatthewBell/GitHub/pollify/client/src/styles/_export.sass
>> @import "@/styles/main.sass";

   -----------------------------^


 @ ./src/styles/_export.sass 4:14-227 14:3-18:5 15:22-235
 @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/About.vue?vue&type=script&lang=js&
 @ ./src/views/About.vue?vue&type=script&lang=js&
 @ ./src/views/About.vue
 @ ./src/router/index.js
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://192.168.2.37:8080/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

If I remove import styles from "@/styles/_export.sass"; the code compiles fine.

I've researched this error and found this post here which seems to imply that my Vue config file is not set correctly. Here is my vue.config.js

module.exports = {
    css: {
        loaderOptions: {
            sass: {
                prependData: `@import "@/styles/main.sass"`
            }
        }
    }
};

Note that main.sass referenced above does not import _export.sass. And again, this has worked fine for me until I tried importing _export.sass into my JS file.

I want to import _export.sass variables into the JS script, as shown above, how can I achieve this?

Matt
  • 1,368
  • 1
  • 26
  • 54
  • Sass imports must always be a relative import. Webpack knows that you mean your src folder with the '@' (probably because of an alias setting somewhere) and replaces them in JS files on compilation, but can't do that for your sass. Changing that might make your import statement valid. – Excalibaard Apr 30 '20 at 11:52
  • That import works though... It's the import line that tries to import 'styles' in 'about.vue' which causes the error. If I remove that, the other import works fine – Matt Apr 30 '20 at 12:07
  • It's even mentioned in the docs that I can use @ in the config file specifically, don't think that's the issue – Matt Apr 30 '20 at 12:08
  • Ah, when I tried to use prependData for vuetify's sass variable import that was one of the caveats I ran into, but I'm using a non-Vue CLI webpack config. The only situation I can think of otherwise is that it could be the order that your loaders are in, because seems it's already transformed once it's handed to sass-loader (I think this because of the presence of the semicolon and the bracket). I hope others may have a more certain answer! – Excalibaard Apr 30 '20 at 12:32
  • 1
    I agree I also thought it has to do with the loader order but can't seem to fix it – Matt Apr 30 '20 at 13:50
  • @Matt - Just to cancel out the obvious, can you add semicolons to the end of your variable statements in `_export.scss` and then test? – Ben Carey May 02 '20 at 20:46
  • Do you mean `:export colorvariable: blue; othercolorvariable: red;` – Matt May 02 '20 at 20:48
  • Just realised you are using SASS, not SCSS. Is there any reason why? I would advise using SCSS instead as the format matches CSS. See here: https://stackoverflow.com/questions/5654447/whats-the-difference-between-scss-and-sass – Ben Carey May 02 '20 at 20:49
  • @Matt - yes, I did mean that but as you are using SASS, I am not sure if that will fix it. I have always used SCSS – Ben Carey May 02 '20 at 20:50
  • I've just always preferred the simplicity of the SASS, I'll try SCSS and report back – Matt May 02 '20 at 20:50
  • The purpose of SCSS is to offer the functionality of SASS, whilst also maintaining the format of CSS. Theoretically, you can copy and paste CSS into a SCSS file and it will work, whereas SASS requires syntax changes – Ben Carey May 02 '20 at 20:51
  • ```Module build failed (from ./node_modules/sass-loader/dist/cjs.js): SassError: media query expression must begin with '(' on line 2 of /Users/MatthewBell/GitHub/pollify/client/src/styles/_export.scss >> :export {``` – Matt May 02 '20 at 20:55
  • After changing it to `_export.scss` and the contents to ```:export { colorvariable: blue; colortwovariable: red; }``` – Matt May 02 '20 at 20:55
  • I have never used SASS so I cannot be certain about the following but I believe that your issue lies in the fact that either the `export` statement is not syntactically correct, or SASS does not support this feature. As your `prependData` seems to work fine, I do not think this is an issue with the loader (although the test will need to be updated to `.scss`) – Ben Carey May 02 '20 at 20:56
  • Another thing you can try is commenting the import in JS, and import `_export.sass` into `main.sass` just to see if it compiles. This will let us narrow things down – Ben Carey May 02 '20 at 20:59
  • Just tried that, it did not compile, throwing the error: ```Module build failed (from ./node_modules/sass-loader/dist/cjs.js): SassError: Invalid CSS after "e": expected 1 selector or at-rule, was "export: {" on line 1 of src/styles/_export.sass from line 5 of src/styles/main.sass from line 1 of /Users/MatthewBell/GitHub/pollify/client/src/views/Home.vue >> export: {``` – Matt May 02 '20 at 21:01
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/212986/discussion-between-matt-and-ben-carey). – Matt May 02 '20 at 21:02

3 Answers3

15

Unfortunately the SASS/SCSS documentation does not mention anything about export, and as such, other than guessing and solving it through trial and error, your best bet is to migrate to SCSS and implement the solution that is widely used (but also not documented).

Personally, I like to import my SCSS variables, and then, export them to JS. So my _export.scss file looks like this:

@import "variables";

:export {

    // Export the color palette to make it accessible to JS
    some-light-blue: $some-light-blue;
    battleship-grey: $battleship-grey;
    // etc...

}

NOTE: It is vitally important that _export.scss is only utilised in JS files, and is not imported in SCSS files. Importing _export.scss into your SCSS files will result in a) unecessary style exports in your CSS, and b) duplications of these style exports throughout every compiled SCSS file

Ben Carey
  • 16,540
  • 19
  • 87
  • 169
  • 5
    is it possible to get this to work with Rollup as well? – Serge van den Oever Jun 04 '20 at 21:41
  • @SergevandenOever I'm asking myself the same question: https://stackoverflow.com/questions/68588047/rollup-allow-export-statement-in-scss-file-to-import-in-js – pmrotule Jul 30 '21 at 09:38
  • I think it is undocumented because it is not a Sass feature but a css-modules one called [ICSS](https://github.com/css-modules/icss) that works with the css-loader with Webpack – PaulCo Aug 16 '21 at 13:34
  • When I use `:export` in one of my SCSS files, I get an webpack error: "Error: Module parse failed: Unexpected token" using sass-loader@13.0.2_sass@1.54.4+webpack@5.74.0 in an Angular / TS app. Any idea what is missing? – Peter T. Nov 11 '22 at 10:36
3

You can use CSS Modules in you Vue SFC styles block, which would look something like this:

<template>
  <button :class="$style.button" />
</template>

<style module>
  .button {
    color: red
  }
</style>

Also please note that often times people are talking about using Sass, but in actuality they are or should be using .scss file type, which is the modern syntax compared to older .sass, but its a matter of taste really.

ux.engineer
  • 10,082
  • 13
  • 67
  • 112
  • 1
    Ah this is very interesting. Thank you for adding this in, I didn't know this was possible! – Matt May 04 '20 at 06:15
1

global.scss

$primary-color: #d51a1a; //Red

:export {
  appColor: $primary-color;
}

app.vue

import variables from '../global.scss'

you can access it by using :

variables.locals.appColor
Aly Radwan
  • 199
  • 3
  • 6