Using Webpack with SASS and PostCSS in Angular2

926 views Asked by At

Init

Im trying to use webpack with the sass-loader and the postcss-loader. I already tried different solutions but nothing worked like I want it to.

I tried the solution from Angular 2 Starter Pack with the raw-loader and the sass-loader, but than the postcss-loader didnt work.

Code

Angular 2 Component

@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls:  ['./app.component.scss']
    // styles: [
    //     require('./app.component.scss')
    // ]
})

Webpack module loader

{
    test: /\.scss$/,
    loaders: ['to-string-loader', 'css-loader', 'postcss-loader', 'resolve-url-loader', 'sass-loader']
}

Problem

With these code lines everything works but the styles are added in the <head> tag within the <style> tag. At some point I would have hundreds of style lines which I want to avoid.

If I change my loader code to this:

loader: ExtractTextPlugin.extract('to-string-loader', 'css-loader', 'postcss-loader', 'resolve-url-loader', 'sass-loader?sourceMap')

and add this to the webpack config

plugins: [
    new ExtractTextPlugin('style.css')
]

it results in an error

Uncaught Error: Expected 'styles' to be an array of strings.

The style.css is actually linked in the html code.

Im searching for a solution which allows me to use sass, postcss and a single .css file.

1

There are 1 answers

0
ge022 On

I just ran into this issue and figured out a solution. I'm pretty sure its the "to-string-loader". The dev config below is working for me using Webpack 4 and Angular 7. It allows a global stylesheet (Tailwind CSS in my case) alongside component styles. Hot module replacement is also working for editing both entries.

entry: {
    app: './src/main',
    styles: './src/assets/styles/styles'
},
resolve: {
    extensions: ['.ts', '.tsx', '.mjs', '.js', '.scss'],
},
module: {
    rules: [
        {
            // Process the component styles
            exclude: path.resolve(__dirname, 'src/assets/styles/styles'),
            test: /\.(scss)$/,
            use: [
                { loader: 'raw-loader' }, // Load component css as raw strings
                {
                    loader: 'postcss-loader', // Process Tailwind CSS
                    options: {
                        sourceMap: 'inline',
                    }
                },
                {
                    loader: 'sass-loader', // Compiles Sass to CSS
                },
            ]
        },
        {
            // Process the global tailwind styles
            include: path.resolve(__dirname, 'src/assets/styles/styles'),
            test: /\.(scss)$/,
            use: [
                {
                    loader: 'style-loader', // Allow for HMR
                },
                {
                    loader: 'postcss-loader', // Process Tailwind CSS
                    options: {
                        sourceMap: 'inline',
                    }
                },
                {
                    loader: 'sass-loader', // Compiles Sass to CSS
                },
            ]
        },
    ]
},

The style-loader will extract the styles into the head at runtime, and allow for HMR. In your prod config, you can use css-loader alongside MiniCssExtractPlugin to extract and inject the global styles as a .css file into the head:

{
    // Process the global tailwind styles
    include: path.resolve(__dirname, 'src/assets/styles/styles'),
    test: /\.(scss)$/,
    use: [
        { loader:  MiniCssExtractPlugin.loader },
        { loader: 'css-loader' },
        {
            loader: 'postcss-loader', // Process Tailwind CSS
            options: {
                sourceMap: false,
            }
        },
        {
            loader: 'sass-loader', // Compiles Sass to CSS
        },
    ]
},