Sandy Gifford
Sandy Gifford

Reputation: 8136

Import SCSS as string

I'm trying to import some SCSS into a Javascript file with mixed results. I've found that this works:

style.styleString.scss

body {
    background: #556;
}

.test {
    &__child {
        color: red;
    }
}

index.js

import "./index.style"; // making sure that nothing we do breaks normal SCSS importing

const css = require("!!raw-loader!sass-loader!./style.stringStyle.scss").default;
console.log(css);

index.style.scss is correctly compiled to a file and style.stringStyle.scss is correctly printed in the console.

What I'd like to do is move this loader pipeline into my webpack config. This is what I have at the moment:

import MiniCssExtractPlugin from "mini-css-extract-plugin";
import path from "path";

const config = {
    mode: "development",
    entry: {
        "app": "./src/index.js",
    },
    output: {
        path: path.resolve(process.cwd(), "dist"),
        filename: "[name].js",
    },
    module: {
        rules: [
            {
                test: /\.stringStyle.scss$/i,
                use: [
                    "raw-loader",
                    "sass-loader",
                ],
            },
            {
                test: /\.scss$/i,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                    },
                    {
                        loader:"css-loader",
                        options: {
                            url: false,
                        },
                    },
                    "sass-loader",
                ],
            },
        ],
    },
    resolve: {
        extensions: [".js", ".scss", ".css"],
    },
    devtool: "source-map",
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].css",
        }),
    ],
};

export default config;

index.js

import "./index.style"; // making sure that nothing we do breaks normal SCSS importing

const css = require("./style.stringStyle.scss").default;
console.log(css);

With this configuration, an empty string is printed to the console (index.style.scss still correctly renders to a file).

What am I doing wrong here? I was sort of under the impression that using the inline ! syntax in imports works just like lining up loaders in the config file, but I'm clearly missing something.

Is it possible to setup loading SCSS files as CSS strings in my Webpack config?

Upvotes: 3

Views: 3061

Answers (1)

Sandy Gifford
Sandy Gifford

Reputation: 8136

Both SCSS tracking rules are getting applied to style.stringStyle.scss. Adding a negative look-behind to the normal import rule's test regex will make sure only the correct rule is selected:

import MiniCssExtractPlugin from "mini-css-extract-plugin";
import path from "path";

const config = {
    mode: "development",
    entry: {
        "app": "./src/index.js",
    },
    output: {
        path: path.resolve(process.cwd(), "dist"),
        filename: "[name].js",
    },
    module: {
        rules: [
            {
                test: /\.stringStyle.scss$/i,
                use: [
                    "raw-loader",
                    "sass-loader",
                ],
            },
            {
                test: /(?<!\.stringStyle)\.scss$/i,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                    },
                    {
                        loader:"css-loader",
                        options: {
                            url: false,
                        },
                    },
                    "sass-loader",
                ],
            },
        ],
    },
    resolve: {
        extensions: [".js", ".scss", ".css"],
    },
    devtool: "source-map",
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].css",
        }),
    ],
};

export default config;

Upvotes: 1

Related Questions