Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

feat: extract multiple css files based on pattern #159

Closed
jimitndiaye opened this issue Mar 9, 2016 · 18 comments
Closed

feat: extract multiple css files based on pattern #159

jimitndiaye opened this issue Mar 9, 2016 · 18 comments

Comments

@jimitndiaye
Copy link

I have three sass files: app.ios.scss, app.wp.scss and app.md.scss.
I'm trying to extract them into seperate files after conversion into css. I've got my loaders configured as follows:

var ExtractTextPlugin = require('extract-text-webpack-plugin');
...
loaders: [
      {
        test: /\.scss$/,
        exclude: root('src', 'app'),
        loader: isTest ? 'null' : ExtractTextPlugin.extract('css?sourceMap!postcss!resolve-url!sass?sourceMap')
      },
],
...
plugins: [
      new ExtractTextPlugin('css/[name].[hash].css', {
          disable: isTest,
          allChunks: false
        })
...
]

If I require a file as '../styles/app.ios.scss' in my app, I'd like it to output an app.ios.css file. Similarly requiring app.wp.scss should output app.wp.css.
Unfortunately all of it is going into one file (css/app.[hash].css), where app is the name of the entry that requests those files.

How do I achieve multiple files as described above? Do I actually have to configure 3 separate loaders?

@romeovs
Copy link

romeovs commented Mar 18, 2016

👍
I would like to use this to output different css files based on pathname. For instance files like *.crit.css would go to [name].crit.css and all the rest goes to main.css.

@lempere
Copy link

lempere commented Jul 26, 2016

+1

1 similar comment
@ghost
Copy link

ghost commented Sep 23, 2016

+1

@mrtom213
Copy link

This worked for me:

Add this at the top of your webpack.config.js:

var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack')

const ExtractNormalCSS = new ExtractTextPlugin("style.css")
const ExtractCriticalCSS = new ExtractTextPlugin("style_crit.css")

Add this into your loaders part:

loaders: [
        ...
        {
        test: /\.css/i,
        exclude: /\.crit.css/,
        loader: ExtractNormalCSS.extract('style', 'css?modules&importLoaders=1&localIdentName=[hash:base64]')
      },
      {
        test: /\.crit.css/i,
        loader: ExtractCriticalCSS.extract('style', 'css?modules&importLoaders=1&localIdentName=[hash:base64]')
      }
]

Add this into plugin part:

plugins: [
        ExtractNormalCSS,
        ExtractCriticalCSS,
    ]

Now it should load

  • .css files into the style.css file.
  • .crit.css files into the style_crit.css file

@jahumes
Copy link

jahumes commented Jan 13, 2017

@mrtom213 I am trying your code from above, but when I use it, I get the same output in both files. Is there anything else you are doing? What version are you using?

@tylerbrostrom
Copy link

@jimitndiaye I've come across this same issue. I feel this is a fairly common use case for people like me who occasionally work on hodgepodge, brown-field projects.

@mrtom213 I wasn't able to successfully build out separate files as per your example. (webpack 2.2.1, extract-text-webpack-plugin 2.1.0)

@bebraw Do you have any thoughts on the usefulness of this proposed enhancement? Thanks!

@bebraw
Copy link
Contributor

bebraw commented Mar 17, 2017

@bro-strummer Three plugin/loader pairs would seem like the solution to me if I understood the problem right. You should be very careful when you set up the loaders to make sure they match only the CSS files you intend. Otherwise you'll get CSS where you don't want it. extract-loader might work for the original problem too.

@wujekbogdan
Copy link

I'm having the same problem. I expected that with multiple entries, configured like this.

entry: [
    './src/js/app.js',
    './src/scss/app.scss',
    './src/scss/login.scss'
],

And a scss loader configured like this:

test: /\.scss$/,
use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: [
        {
            loader: 'css-loader',
            options: {
                sourceMap: true
            }
        },
        {
            loader: 'resolve-url-loader'
        },
        {
            loader: 'postcss-loader'
        },
        {
            loader: 'sass-loader',
            options: {
                sourceMap: true
            }
        }
    ]
})

And finally, with the following plugins section:

plugins: [
    new ExtractTextPlugin('/css/[name].css'),
    // Other plugins ...
],

I will get separate 2 files: dist/css/app.css and dist/css/login.css. But there's only one file extracted, it contains a result of app.scss and login.scss compilation concactonated together.

But what's more weird - the output file name is main.scss, so it seems that the [name] tag is ignored. I also tried the following syntax:

new ExtractTextPlugin({
  filename: '[name].css'
});

But it doesn't work either.

@bebraw
Copy link
Contributor

bebraw commented Apr 3, 2017

@wujekbogdan Instead of

entry: [
    './src/js/app.js',
    './src/scss/app.scss',
    './src/scss/login.scss'
],

could you try something along

entry: {
  app:  './src/js/app.js',
  appStyle: './src/scss/app.scss',
  loginStyle: './src/scss/login.scss'
}

[name] picks up the keys from there so tweak accordingly.

@NogsMPLS
Copy link

NogsMPLS commented Apr 7, 2017

the suggestion of using extract-loader worked best me. just did this:

use: [ 'file-loader?name=[name].css', 'extract-loader', 'css-loader', 'sass-loader' ]

and it converted .scss file into css file of the same name. could add url loader and postcss in there to optimize a bit more also.

no need for keeping a massive list of entry points either (this project had like a good 60 that would've been needed)

@wujekbogdan
Copy link

wujekbogdan commented Apr 9, 2017

@bebraw

I've changed my configuration entry to:

    entry: {
        appJs: './src/js/app.js',
        appCss: './src/scss/app.scss',
        loginCss: './src/scss/login/login.scss'
    },

Indeed, it works (however it's confusing, because in loaders [name] is used in a different way - in loaders, it just means the original file name) but after applying this change some errors which I do not understand appeared in the console.

This is the console output:

 ERROR  Failed to compile with 2 errors                                                                     15:34:59


 error  in js/app.js

Conflict: Multiple assets emit to the same filename js/app.js

 error  in js/app.js

Conflict: Multiple assets emit to the same filename js/app.js

Hash: 89335d0bab6f5c1c57c1
Version: webpack 2.3.3
Time: 8274ms
                Asset     Size  Chunks             Chunk Names
      /css/appCss.css   140 kB       2  [emitted]  appCss
    /css/loginCss.css  2.34 kB       1  [emitted]  loginCss
/css/loginCss.css.map  11.1 kB       1  [emitted]  loginCss
  /css/appCss.css.map   856 kB       2  [emitted]  appCss

ERROR in chunk loginCss [entry]
js/app.js
Conflict: Multiple assets emit to the same filename js/app.js

ERROR in chunk appCss [entry]
js/app.js
Conflict: Multiple assets emit to the same filename js/app.js

And there's one more issue. I want my files to be named app.css and app.js (so I want to have the same input and the output files names), but I can't do it because a JS object's keys must be unique, so the following syntax is invalid:

    entry: {
        app: './src/js/app.js',
        app: './src/scss/app.scss',
        login: './src/scss/login/login.scss'
    },

// Edit:

Thanks @NogsMPLS, I also gave the extract-loader a try. Nom my entry section looks like this:

    entry: [
        './src/js/app.js',
        './src/scss/app.scss',
        './src/scss/login/login.scss'
    ],

And the part that's responsible for the SCSS compilation/extraction looks like the following:

{
    test: /\.scss$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: '[name].css',
                context: './src/css/',
                outputPath: 'css/',
                publicPath: '../'
            }
        },
        {
            loader: 'extract-loader'
        },
        {
            loader: 'css-loader',
            options: {
                sourceMap: true
            }
        },
        {
            loader: 'resolve-url-loader'
        },
        {
            loader: 'postcss-loader'
        },
        {
            loader: 'sass-loader',
            options: {
                sourceMap: true
            }
        }
    ]
}

So now, finally, login.css and app.css are compiled as separate files under the ./dist/css/ directory. The configuration wasn't straightforward. I had to play a little in order to find a proper loaders order :).

Webpack is so powerful tool, but so badly documented...

@firestar300
Copy link

firestar300 commented Apr 19, 2017

Same issue for me. I have a payment.css and I would like to compile to payment.css in my distfolder.

    entry: {
        payment:                './src/styles/payment.css'
    }

And my plugins array:

plugins: [new ExtractTextPlugin('styles/[name].css')]

Finally I have a payment.js in my dist folder. Wtf ?

Edit : I finally use https://github.com/kevlened/copy-webpack-plugin to simply copy files from source to dist.

@michael-ciniawsky michael-ciniawsky changed the title Extract multiple css files based on pattern feat: extract multiple css files based on pattern Apr 22, 2017
@karim10
Copy link

karim10 commented Jan 19, 2018

@wujekbogdan I'm trying to adapt your solution and I got this error:
'No PostCSS Config found'
do we a postcss config in our scss files??
Thank you

@wujekbogdan
Copy link

@karim10
The example I posted was only for explanation purposes (I copied a part of my real config). Don't copy-paste it as it is. The error that you see "No PostCSS Config found" means... that you don't have PostCSS config :) So if you don't use PostCSS then simply remove the postcss loader entry from the Webpack config (it applies to all other loaders).

@karim10
Copy link

karim10 commented Jan 22, 2018

@wujekbogdan Thanks a lot 😅

@alexander-akait
Copy link
Member

alexander-akait commented Feb 1, 2018

Solved, please see #159 (comment). Thanks for everyone. Feel free to feedback.

@alexander-akait
Copy link
Member

Oh, sorry, it should be solved using only ETWP

@michael-ciniawsky
Copy link
Member

ETWP entered maintenance mode and won't receive any feature updates, please open an issue in mini-css-extract-plugin instead

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests