Caleb Jay
Caleb Jay

Reputation: 2199

Import a SCSS "exported" variable into the Javascript code within a .vue file that is loaded by vue-loader and bundled by webpack

I have a variable in my vars.scss that I want to access from Javascript in root/app/app.vue.

root/app/scss/vars.scss

:export {
    cursor: #fff;
}

root/app/app.vue

<template>
  <div id="yes">
  </div>
</template>

<script lang="ts">
import Vue from 'vue';
import colors from '@/scss/vars.scss';

export default Vue.extend({
  mounted() {
    console.log(colors.cursor);
  },
});
</script>

<style >
</style>

I have read approximately 30 different stackoverflow questions that appear to be dealing with the similar problem of importing variables into the style block of the .vue file, as well as the identical problem of importing the variables directly into the Javascript code. As a result, my webpack.config.js looks like the following:

root/webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const env = process.env.NODE_ENV

module.exports = {
  entry: './app/index.ts',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'staticfiles')
  },
  resolve: {
    extensions: [ '.ts', '.js', '.vue', '.scss', '.sass'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': path.resolve(__dirname, '/app/')
    }
  },
  plugins: [
    new HtmlWebpackPlugin(),
    new CleanWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new VueLoaderPlugin()
  ],
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.(js|vue|ts)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
            // the "scss" and "sass" values for the lang attribute to the right configs here.
            // other preprocessors should work out of the box, no loader config like this necessary.
            'scss': 'vue-style-loader!css-loader!sass-loader',
            'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
          }
          // other vue-loader options go here
        }
      },
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      },
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        exclude: /node_modules/,
        options: {
          appendTsSuffixTo: [/\.vue$/],
        }
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      },
      {
        test: /\.s(a|c)ss$/,
        use: [ {
          loader: "style-loader",
          options: {
            sourceMap: env === 'development',
          }
        }, {
          loader: "css-loader",
          options: {
            sourceMap: env === 'development',
          }
        }, {
          loader: "sass-loader",
          options: {
            sourceMap: env === 'development',
          }
        },
        'vue-style-loader'],
      }]
  }
};

I have also tried, in the test: /\.s(a|c)ss$/ section, to put vue-style-loader at the beginning of the array.

I have tried many combinations of filenames when attempting to import the .scss file, such as relative (../scss/vars.scss), removing the extension, using .css as an extension, etc.

The error I get is:

ERROR in /home/Documents/application/app/app.vue.ts
[tsl] ERROR in /home/Documents/application/app/app.vue.ts(10,28)
      TS2307: Cannot find module '@/scss/vars.scss'.

My question:

In a project that uses vue-style-loader and vue-loader to build .vue files with webpack, how can I import .scss variables into the <script> portion of a .vue file? (please note - I am NOT attempting to import them into the <style> section of the .vue file)

Upvotes: 1

Views: 1130

Answers (1)

Stephen Thomas
Stephen Thomas

Reputation: 14043

An example based on my comment:

SCSS fragment:

$foo: #333;

body {
    --variable-foo: $foo;
}

And then anywhere in the JavaScript

const value = document.body.style.getPropertyValue("--variable-foo");
console.log(value); // outputs "#333"

Upvotes: 1

Related Questions