Pass webpack (environment) variable to scss file
Asked Answered
E

3

5

Very new to webpack... I would like to be able to read a value, in this case specifically the value of env from webpack.config.js in a sass file, so I can have different css based on environment.

For example:

  • env = development, colour = green
  • env = production, colour = blue

So far I have focoused on sass-loader, trying to pass data, but has not worked, the $env variable is always undefined when i run npm run build:Debug (this runs webpack --app=all --env=development).

These are the files I have:

webpack.config.js

const path = require("path");
const common = require("./.webpack/webpack.common.config");

const config = [];

function addAppConfig(app) {
    app.module = common.module;
    app.resolve = common.resolve;
    config.push(app);
}

module.exports = (env, argv) => {
    switch (argv.app) {
    // Add new configs to below
    case "a":
        addAppConfig(aa);
        break;

    case "b":
        addAppConfig(bb);
        break;

    case "c":
        addAppConfig(cc);
        break;
        
    default:
    case "all":
        addAppConfig(xyz);
    }

    switch (env) {
    case "local":
        config.forEach(appConfig => {
            // The "development" mode configuration option tells webpack to use its built-in development optimizations
            // https://webpack.js.org/configuration/mode/#mode-development
            appConfig.mode = "development";
            appConfig.output.path = path.resolve(__dirname, "../dist");
            appConfig.output.publicPath = "http://localhost:3000/dist";
            appConfig.devtool = "inline-source-map";
            appConfig.devServer = {
                contentBase: path.resolve(__dirname, "./public"),
                port: "3000",
                watchContentBase: true
            };
        });

        break;

    case "development":
        config.forEach(appConfig => {
            // The "development" mode configuration option tells webpack to use its built-in development optimizations
            // https://webpack.js.org/configuration/mode/#mode-development
            appConfig.mode = "development";
            appConfig.devtool = "inline-source-map";
        });

        break;

    default:
    case "production":
        config.forEach(appConfig => {
            // The "production" mode configuration option tells webpack to use its built-in production optimizations including minification etc.
            // https://webpack.js.org/configuration/mode/#mode-production
            appConfig.mode = "production";
            appConfig.devtool = "cheap-source-map";
        });

        break;
    }

    return config;
};

webpack.common.config.js - this is used in webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
                test: /\.(s*)css$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            name: "[name].css"
                        }
                    },
                    "extract-loader",
                    "css-loader",
                    "sass-loader"
                ]
            },
            {
                test: /\.(png|jp(e*)g)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            // Convert images < 8kb to base64 strings
                            limit: 8000,
                            name: "images/[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /\.(svg)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            // 80kb limit to avoid an IE11 display bug
                            limit: 80000,
                            name: "images/[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            // Convert images < 8kb to base64 strings
                            limit: 8000,
                            name: "fonts/[name].[ext]"
                        }
                    }
                ]
            }
        ]
    },
    resolve: {
        extensions: [".js", ".jsx"]
    }
};

and finally: document.scss

.aside__left, .aside__right {
    @if $env == 'development' {
        background-color: red; 
      } @else {
        background-color: green;
      }
      background-color: $desiredColor;
}

Is there a way to have scss variable mapping/passing from webpack config, or any other way that based on environment, there would be different css generated?

Extroversion answered 4/2, 2020 at 13:21 Comment(0)
R
8

You can pass variable from webpack config to scss file with the following method:

{
    loader: "sass-loader",
    options: {
        data: "$var1: " + yourVar1+ ";"
    }
}

(c) https://github.com/webpack-contrib/sass-loader/issues/49#issuecomment-284131561

Renter answered 12/3, 2020 at 0:55 Comment(2)
This is no longer valid: ` - options has an unknown property 'data'. These properties are valid: object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }` The documentation also mentions explicitly that data is ignored webpack.js.org/loaders/sass-loader/#sassoptionsLaid
data should be replaced with additionalDataPanegyric
I
6

This question is already answered and it's correct, but really I searched a lot to identify how to use it in SASS file and connect SASS with webpack env. I would like to add that to my answer.

package.json

Here we are adding NODE_ENV variable in webpack.config.js. To add to env to package.json, please refer: webpackenvironmentconfiguration

"build:dev": "webpack --env.NODE_ENV=dev --config  webpack.config.js --progress",

webpack.config:

Now, add those variables here, which you want to use based on environment. like, I want to add environment to my dynamic url of background image.

{
    loader: "sass-loader",
    options: {
        data: "$var1: " + env.NODE_ENV + ";"
    }
}

_variables.scss

You can use it in your .sass file in any one way:

$image-url: "https://" + $var1 + ".mysite.net/images/ping.jpg"; or
$image-url: "https://#{$var1}.mysite.net/images/ping.jpg";

Output

Your output url will be something like this:

https://dev.mysite.net/images/ping.jpg
Idaho answered 29/8, 2020 at 23:14 Comment(2)
Note that as-of sass-loader v8 "data" has been changed to "prependData": github.com/webpack-contrib/sass-loader/issues/760Heliostat
Since sass-loader v9, the option is now additionalData (ref github.com/webpack-contrib/sass-loader/blob/master/…)Inmesh
D
1

@gorodezkiy is right, only the key name is not data, but additionalData (since a while), so:

{
    loader: "sass-loader",
    options: {
        additionalData: "$var1: " + yourVar1+ ";"
    }
}

https://github.com/webpack-contrib/sass-loader/issues/865

Danieladaniele answered 27/9, 2023 at 10:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.